【问题标题】:Make mp3 seekable PHP使 mp3 可搜索 PHP
【发布时间】:2012-07-05 14:50:15
【问题描述】:

我做了这个 PHP 脚本

$file_name = 'sample.mp3'; header('内容类型:音频/mpeg'); $opts = 数组('http' => 大批( '方法' => 'GET', 'protocol_version' => 1.1, ) ); $context = stream_context_create($opts); $stream = fopen($file_name, 'rb', FALSE, $context); $metadata = stream_get_meta_data($stream); $data = stream_get_contents($stream); 打印($数据); fclose($流);

它可以成功流式传输 mp3 媒体,但我无法找到也在 html5 中播放的 mp3 文件 video 标签无法从中提取元数据,请告诉我我做错了什么以及如何使这个过程正常工作,谢谢

【问题讨论】:

    标签: php html


    【解决方案1】:

    在这里试试这个,支持部分下载和寻找任何文件大小,现在也可以在 chrome 中正常工作:

    <?php 
    $file_name = './sample.mp3';
    stream($file_name, 'audio/mpeg');
    
    /**
     * Stream-able file handler
     *
     * @param String $file_location
     * @param Header|String $content_type
     * @return content
     */
    function stream($file, $content_type = 'application/octet-stream') {
        @error_reporting(0);
    
        // Make sure the files exists, otherwise we are wasting our time
        if (!file_exists($file)) {
            header("HTTP/1.1 404 Not Found");
            exit;
        }
    
        // Get file size
        $filesize = sprintf("%u", filesize($file));
    
        // Handle 'Range' header
        if(isset($_SERVER['HTTP_RANGE'])){
            $range = $_SERVER['HTTP_RANGE'];
        }elseif($apache = apache_request_headers()){
            $headers = array();
            foreach ($apache as $header => $val){
                $headers[strtolower($header)] = $val;
            }
            if(isset($headers['range'])){
                $range = $headers['range'];
            }
            else $range = FALSE;
        } else $range = FALSE;
    
        //Is range
        if($range){
            $partial = true;
            list($param, $range) = explode('=',$range);
            // Bad request - range unit is not 'bytes'
            if(strtolower(trim($param)) != 'bytes'){ 
                header("HTTP/1.1 400 Invalid Request");
                exit;
            }
            // Get range values
            $range = explode(',',$range);
            $range = explode('-',$range[0]); 
            // Deal with range values
            if ($range[0] === ''){
                $end = $filesize - 1;
                $start = $end - intval($range[0]);
            } else if ($range[1] === '') {
                $start = intval($range[0]);
                $end = $filesize - 1;
            }else{ 
                // Both numbers present, return specific range
                $start = intval($range[0]);
                $end = intval($range[1]);
                if ($end >= $filesize || (!$start && (!$end || $end == ($filesize - 1)))) $partial = false; // Invalid range/whole file specified, return whole file
            }
            $length = $end - $start + 1;
        }
        // No range requested
        else $partial = false; 
    
        // Send standard headers
        header("Content-Type: $content_type");
        header("Content-Length: " . ($partial ? $length : $filesize));
        header('Accept-Ranges: bytes');
    
        // send extra headers for range handling...
        if ($partial) {
            header('HTTP/1.1 206 Partial Content');
            header("Content-Range: bytes $start-$end/$filesize");
            if (!$fp = fopen($file, 'rb')) {
                header("HTTP/1.1 500 Internal Server Error");
                exit;
            }
            if ($start) fseek($fp,$start);
            while($length){
                set_time_limit(0);
                $read = ($length > 8192) ? 8192 : $length;
                $length -= $read;
                print(fread($fp,$read));
            }
            fclose($fp);
        }
        //just send the whole file
        else readfile($file);
        exit;
    }
    ?>
    

    【讨论】:

    • @joshkrz - 您应该确保在设置标题之前不发送任何输出(空格、html),您得到的错误会告诉您输出的位置。
    • @joshkrz 异常行会在页面上回显,我不确定您是如何调用它的,但您应该将其包装在 try{}catch(){} 中以捕获异常。
    • @joshkrz 功能现已针对 chrome 修复,希望对您有所帮助
    • @Loz Cherone Content-Length 应该是您发送的长度。这并不总是文件大小($file)。
    • 实际上(提出了建议的编辑,但现在我无法撤消),我认为 Content-Length 应该更像:header("Content-Length: " . ($range ? ($end - $start + 1) : $filesize));
    【解决方案2】:

    这应该有望解决您的问题,请遵循此方法。

    您需要做的是使用readfile() 并设置file_exists(),这样您就可以知道您正在打开正确的文件。

    $extension = "mp3";
    $mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";
    
    if(file_exists($file_name)){
        header('Content-type: ' . $mime_type);
        header('Content-length: ' . filesize($file_name));
        header('Content-Disposition: filename="' . $file_name);
        header('X-Pad: avoid browser bug');
        header('Cache-Control: no-cache');
        readfile($file_name);
    }
    

    Reference

    【讨论】:

    • 我希望它缓冲,我怎么能?
    • 如上所述,这没有Content-Range;在 Chrome 中,目前(5 年后)没有它是不可能设置 currentTime 的。
    • header('Content-typ... 缺少双引号和解决方案不起作用
    猜你喜欢
    • 2015-07-25
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多