有可能使用PHP重新流网络广播吗?(PHP guru需要)

myss37ts  于 2023-06-20  发布在  PHP
关注(0)|答案(4)|浏览(108)

是否可以使用PHP重新传输网络广播?

无线电在端口8000可用。我想使用我的网络服务器和“传输”的无线电流端口80。
这可能吗?
我已经在谷歌上搜索过了,我找到了http://support.spacialnet.com/forums/viewtopic.php?f=13&t=16858&start=15,但它对我不起作用。* 它确实起作用。在我忘记更改流的MIME类型之前。
我从前面提到的URL(http://support.spacialnet.com/forums/viewtopic.php?f=13&t=16858&start=15)。它现在确实起作用了,但是在听了大约8分钟后,水流总是会中断。知道为什么吗(服务器最大值)执行时间设置为30秒)。我用不同的比特率测试了不同的流,但它每次的行为都完全相同。有什么帮助吗?

xhv8bpkk

xhv8bpkk1#

我不应该告诉你这些。但从纯学术的Angular 来看,您可能希望使用fpassthru。这将允许您加载一个文件(在本例中是一个流),并立即将其转储出去,只要需要。(对于一条小溪来说,那就是永远。)
至于具体细节,这可能看起来很像你提供的链接。
可能问题:脚本的最大运行时间可能成为一个问题。我不确定如果是这样的话,你总是可以把它增加到你在给定的听力中不太可能达到的程度。
最后,别这样...

xyhw6mcr

xyhw6mcr2#

我可能不应该回答这个问题,但我在工作中有一些空闲时间,想玩一下套接字。
这是我的类,它没有经过很好的测试(好吧,它在第一次运行时工作,这是可疑的),可能有错误,但它可能会给予你一些有用的想法。它剥离ICY* 标题,如您发布的示例,但这可以很容易地改变。
我在Ubuntu图腾播放器上测试了它,在我停止它之前,它运行了10分钟,但也许我只是运气好(:至少8分钟似乎不是一个神奇的数字。

<?php

ob_start();

class RadioProxy {
    CONST STREAM_content_type='audio/aac';
    CONST STREAM_timeout=1.5;

    CONST HTTP_response_header_first='/\s200\s/';
    CONST HTTP_response_header_pattern='/^[a-z\-]+:/i';
    CONST HTTP_max_line_length=1024;

    CONST HTTP_delim="\r\n";
    CONST HTTP_max_response_headers=40;
    CONST ERROR_max=5;
    CONST ERROR_interval=120;
    CONST ERROR_usleep=300000;

    private $server_name, $server_port;
    private $HTTP_headers;
    private $STREAM = NULL;
    private $STREAM_errors = array();
    private $TIMEOUT_seconds, $TIMEOUT_microseconds;

    public function __construct($server_name, $server_port, $filename='') {
        self::STREAM_set_headers();
        $this->server_name = $server_name;
        $this->server_port = $server_port;
        $this->HTTP_headers = $this->HTTP_generate_headers($filename);
        $this->connect();
    }

    private function connect() {
        $HTTP_headers_length = strlen($this->HTTP_headers);
        do {

            if (!$this->STREAM_connect()) {
                continue;
            }

            if (!$this->STREAM_send_headers()) {
                continue;
            }

            if (!$this->STREAM_skip_headers()) {
                continue;
            }

            if (!$this->STREAM_proxy()) {
                continue;
            }
        } while ($this->ERROR_is_accepteble());
    }

    private function HTTP_generate_headers($filename) {
        $header = '';
        self::HTTP_add_header($header, 'GET /' . rawurlencode($filename) . ' HTTP/1.0');
        self::HTTP_add_header($header, 'Host: ' . $this->server_name);
        self::HTTP_add_header($header, 'User-Agent: WinampMPEG/5.11');
        self::HTTP_add_header($header, 'Accept: */*');
        self::HTTP_add_header($header, 'Connection: close');
        //End of headers
        self::HTTP_add_header($header);
        return $header;
    }

    private static function HTTP_add_header(&$header, $new_header_line='') {
        $header.=$new_header_line . self::HTTP_delim;
    }

    private function ERROR_is_accepteble() {
        //Delete old errors
        array_filter($this->STREAM_errors, 'self::ERROR_remove_old');
        $this->STREAM_errors[] = time();
        usleep(self::ERROR_usleep);
        return count($this->STREAM_errors) <= self::ERROR_max;
    }

    private static function ERROR_remove_old($error_time) {
        return ($error_time - time()) <= self::ERROR_interval;
    }

    private function STREAM_connect() {
        if (!ob_get_level()) {
            ob_start();
        }
        ob_clean();
        if ($this->STREAM !== NULL) {
            fclose($this->STREAM);
        }
        $this->STREAM = fsockopen($this->server_name, $this->server_port);

        if ($this->STREAM === FALSE) {
            return FALSE;
        }

        $this->TIMEOUT_seconds = floor(self::STREAM_timeout);
        $this->TIMEOUT_microseconds = ceil((self::STREAM_timeout - $this->TIMEOUT_seconds) * 1000);
        return stream_set_timeout($this->STREAM, $this->TIMEOUT_seconds, $this->TIMEOUT_microseconds);
    }

    private function STREAM_send_headers() {
        return fwrite($this->STREAM, $this->HTTP_headers) === strlen($this->HTTP_headers);
    }

    private function STREAM_skip_headers() {
        $read_expect = array($this->STREAM);

        $if_first_header = true;
        $header_lines_count = 0;

        do {
            stream_select($read_expect, $NULL, $NULL, $this->TIMEOUT_seconds, $this->TIMEOUT_microseconds);

            $header_line = stream_get_line($this->STREAM, self::HTTP_max_line_length, self::HTTP_delim);

            if ($header_line === FALSE) {
                return FALSE;
            }
            if ($if_first_header) {
                $if_first_header = false;

                if (!preg_match(self::HTTP_response_header_first, $header_line)) {
                    return FALSE;
                }
                continue;
            }

            if (empty($header_line)) {
                return TRUE;
            }

            if (!preg_match(self::HTTP_response_header_pattern, $header_line)) {
                return FALSE;
            }

            $header_lines_count++;
        } while ($header_lines_count < self::HTTP_max_response_headers);

        return FALSE;
    }

    private function STREAM_proxy() {
        $read_expect = array($this->STREAM);

        //No output buffering should be here!
        while (@ob_end_clean ());

        do {
            stream_select($read_expect, $NULL, $NULL, $this->TIMEOUT_seconds, $this->TIMEOUT_microseconds);
        } while (fpassthru($this->STREAM));
    }

    private static function STREAM_set_headers() {
        //Clean all output
        ob_clean();
        header("Content-type: " . self::STREAM_content_type);
        ob_flush();
    }

}

$TestRadio = new RadioProxy('XXX.XXX.XXX.XXX', XXXX,'XXXX.mp3');

P.S.别这样。

p8ekf7hl

p8ekf7hl3#

技术上绝对可行。我会尝试使用wireshark来查看数据包。在8分钟的标记处可能缺少SHOUTcast专有的东西。
你也可以试着缓冲一下。可能是水流停滞了?

dy2hfwbg

dy2hfwbg4#

从逻辑的Angular 来看,这里没有法律可以被打破。需要假设一个人正在收听一个设备,而这是不可知的。
我们知道在家庭中,多个人可以观看同一设备。
此外,多个设备可以在一个位置流式传输一个电台,但这并不等同于听众的数量。可能有100个设备和1个人在物理上收听其中的任何一个。

相关问题