跳过MP3会导致播放器在Webkit浏览器中损坏

约瑟克(Joshkrz)

我有一个PHP脚本,可以充当用户和MP3之间的代理。这是为了防止外部嵌入或热链接,因此我可以计算每个MP3文件的播放次数。

我在Google Chrome和Safari(Opera,Firefox和Internet Explorer可以正常运行)中遇到问题,它们可以很好地播放MP3,但我也可以尝试,但只能搜索有限的次数。尝试几次后,播放器将自身变灰(本机chrome播放器)或显示错误(audio.jsJWPlayer 6)。我可以再次按播放,它将重新启动,但是在出现此类错误后,audio.js不会再次显示播放按钮。

JWPlayer在控制台中引发以下错误:

MediaError
code: 2

__proto__: MediaError
MEDIA_ERR_ABORTED: 1
MEDIA_ERR_DECODE: 3
MEDIA_ERR_ENCRYPTED: 5
MEDIA_ERR_NETWORK: 2
MEDIA_ERR_SRC_NOT_SUPPORTED: 4

在chromes原生播放器中,控制台报告“无法加载资源”,“我的服务器错误日志”未显示任何错误。

我当前使用的代码来自Los Cherone的答案: 使mp3可查找PHP

我以前的解决方案是不再使用此代码,但是在这里供参考:

<?php 
$track = '/public_html/mp3-previews/' . $_GET['stream'];

if(file_exists($track)) {
    header('Content-type: audio/mpeg');
header('Accept-Ranges: bytes');
    header('Content-length: ' . filesize($track));
    print file_get_contents($track);
} else {
    echo "no file";
}
?>

两种代码均会导致此错误,但值得指出的是,两种代码均流音频,并且它们都允许我搜索几次。

我最初的想法是apache_request_headers函数引起了这个问题,因为我正在运行PHP 5.3,而我的主机正在将PHP作为Fast CGI运行。因此,对于Los Cherone的代码,我正在使用此替代方法,但是为什么我的第一次尝试也不起作用?

编辑:这不是问题。我已经更新了我的PHP版本,这仍然导致我遇到问题。

这是我的托管服务器示例:http : //tabbidesign.com/audio/

Los Cherone的代码和我自己的本地Apache服务器以及PHP 5.4.9的完美结合使用,不会发生此问题。这是示例:http : //tabbicat.info/proving/audio/

是什么原因造成的?

约瑟克(Joshkrz)

我设法解决了我的问题。

在尝试了其他传输方法之后,使用Fiddler分析了我的网络流量,并从上面的评论中获取了一些建议,我对代码进行了一些更改。

由于某种原因,脚本在如下所示的循环中未发送正确数量的字节:

if ($start) fseek($fp,$start);
    while($length){
        set_time_limit(0);
        $read = 8192;
        $length -= $read;
        print(fread($fp,$read));
    }
    fclose($fp);

在Firefox,Opera和IE中没有问题的原因是,它们在播放期间缓存了整个文件,因此向后跳过就不再请求该文件。Webkit(Chrome和Safari)再次请求文件,每次发送内容范围。

$file_name  = '/home/sites/public_html/mp3-previews/' . $_GET['stream'];
stream($file_name, 'audio/mpeg');


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: $length");
header('Accept-Ranges: bytes');
//header('Connection: keep-alive');

//header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
//header('Pragma: no-cache'); // HTTP 1.0.
//header('Expires: 0'); // Proxies.

// 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);
        print(fread($fp,$length));
        fclose($fp);
}
//just send the whole file
else readfile($file);
exit;
}

我已经发送了Content-Length标头中请求的实际输出大小,并且删除了以8000字节为单位发送文件的循环。

现在,我可以确定,如果我尝试处理大文件,PHP肯定会用光内存,因为我要处理整个文件而不是8000字节的块,但是我每次只处理4MB的文件,所以现在可以了。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在浏览器中播放 MP3

Android中的MP3 /音乐播放器

浏览器中的mp3流解码

浏览器中的MP3音频支持

在MP3播放器上重新全新安装Rockbox时,拔出插头会导致“访问播放列表控制文件时出错”

如何在播放mp3时在播放器中显示图像?

Java中带有计时器的MP3播放器[快进]

建议最低要求的MP3播放器

不可携式MP3播放器(硬件)

jPlayer-多实例mp3播放器

如何在Safari / IE浏览器中检测HTML5或Javascript中用于播放mp3而非webm的浏览器类型?

IE浏览器无法从PHP脚本播放MP3

如何通过单击将 mp3 链接加载到音频播放器中

如何减少 android 音乐播放器中的音频(MP3 文件)加载时间?

为什么不能在汽车播放器中播放mp3 CD,而在计算机上播放?

当我在 mp3 播放器中多次点击播放按钮时,我的应用程序崩溃了

如何在Android的简单播放器中从原始播放mp3文件?

可以播放MP3并显示背景图像的JavaScript播放器吗?

如何将播放列表从Banshee复制到MP3播放器?

Linux命令行音乐播放器播放mp3流

MP4碎片-在浏览器中播放问题

如何在未在浏览器中打开的情况下从Podbean下载mp3?

在旧浏览器的页面中检测MP3支持

将标签添加到mp3中以便在音乐播放器中使用

来自GOM播放器的字幕浏览器消失了

通过浏览器在外部视频播放器中打开Youtube链接

安装小型mp3播放器时,Linux有很多依赖项

将音乐文件从ubuntu传输到mp3播放器

使用ubuntu 16.04无法显示USB mp3播放器