- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 PHP 脚本充当用户和 MP3 之间的代理。这是为了防止外部嵌入或热链接,因此我可以计算每个 MP3 文件的播放次数。
我在 Google Chrome 和 Safari(Opera、Firefox 和 Internet Explorer 完美运行)中遇到问题,它可以很好地播放 MP3,我也可以搜索,但次数有限。搜索几次后播放器变灰(原生 chrome 播放器)或显示错误(audio.js 和 JWPlayer 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
在 chrome native player 中,控制台报告“无法加载资源”,我的服务器错误日志显示没有错误。
我目前使用的代码来自 Los Cherone 的回答: Make mp3 seekable 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 的代码,我使用这个 workaround ,但为什么我的第一次尝试也不起作用?
编辑:这不是问题所在。我已经更新了我的 PHP 版本,但问题仍然存在。
这是我的托管服务器示例: http://tabbidesign.com/audio/
Los Cherone 的代码和我自己的本地 Apache 服务器与 PHP 5.4.9 的组合工作完美,不会出现这个问题。这是示例:http://tabbicat.info/proving/audio/
这可能是什么原因造成的?
最佳答案
我已经设法解决了我的问题。
在尝试了其他传输方法、使用 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 header 中请求的实际输出大小,并且我已经删除了以 8000 字节为单位发送文件的循环。
现在我确信,如果我尝试处理大文件,PHP 肯定会耗尽内存,因为我正在处理整个文件而不是 8000 字节的 block ,但我每次只处理 4MB 的文件,所以现在这是好的。
关于javascript - 跳过 MP3 会导致播放器在 Webkit 浏览器中中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21538608/
我的算法- private static MyList skip$DeleteItem(MyList L , int M , int N){ MyList curr = L; MyLi
我正在 SWI-Prolog 下开发,但我的目标是 Erlog (https://github.com/rvirding/erlog)。我需要一种使用非标准 Prolog 语法的方法。 有没有办法
我正在尝试从应用程序下载一大堆文件。它的shell命令是“下载文件名”。 我有一个文本文件,其中包含必须下载的所有文件名。我要做的就是运行一个脚本/命令,以便在执行上述命令时 1.从文本文件中提取文件
我试图循环遍历所有用户的评论,但使用 if 语句查找特定值。问题是我的应用程序崩溃了,因为一些用户没有发表评论,因此我得到“无法读取‘收集’未定义的属性”。如何跳过 if 语句的未定义值?代码如下:
我们有按年份分区的索引,例如: items-2019 items-2020 考虑以下数据: POST items-2019/_doc { "@timestamp": "2019-01-01" }
我只是编写一个页面来按实体编号查看每个 ASCII 条目,我想知道是否有一种更简单/更干净的方法来跳过不需要的数字。 var x = new Ar
我希望能够普遍使用重复条目,但也能够跳过特定日期。例子: ** TODO swim practice SCHEDULED 但是,我提前知道 2013-12-25 不会有练习。但是,当我将项目标
如何跳过像这样的 for 循环的一次迭代: for (int i = 65; i <= 90; i++) { if (!(i == 73)) { uniq.add((char) i);
这个问题已经存在: Scanner issue when using nextLine after nextXXX [duplicate] 已关闭 9 年前。 ask=1; while(ask==1)
我在使用一个程序时遇到了一些麻烦,我应该允许用户在程序中输入任意数量的数字,直到他们不再想要为止。然后程序应该计算输入数字的平均值和最大值。我哪里做错了? import java.util.Scann
我有一个名为segments的 Sprite 数组,我想在每个循环中跳过segments的第一个元素。我目前正在这样做: var first = true; for each (var segment
我目前正在编写一个 for 循环来遍历包含 38 个元素的 2D。然而,其中一些元素为空,我希望 for 循环简单地跳过它们(因为在我正在解决的难题中,它们没有与它们相关的移动)。快速搜索表明,我可以
我想使用pre-commit处理我的 git 项目的 git hooks。但是,当我使用它时,git commit 命令不断跳过 unittest 执行: (smartexchange) trnboo
这个问题在这里已经有了答案: Does scanf() take '\n' as input leftover from previous scanf()? (1 个回答) 关闭 9 年前。 我正在
我正在迭代 csv 文件中的每一行,并仅选择/计算满足条件的行。但是,当连续出现错误时,它会停止循环。有没有办法告诉 python 跳过错误并移动到下一行?我使用了 try 函数但没有工作。我的代码是
感谢您提供的优秀示例,我试过了,它按我的预期工作。很高兴看到有人了解问题的本质。但是,我认为我应该用 Lift 标记问题,因为我正在使用 Lift 框架,这就是(仍然)发生这个问题的地方(尽管我仍然认
大家好,我正在编写一个算法来从 NodeTree 中删除具体分支(例如 DSF)。如果您选择 Node 的名称,算法将检查该 Node 是否是其他 Node 的父 Node ;如果是,它会获取该 No
附有代码和输出。 基本上它是第二次跳过我的输入。就像我启动代码一样,它让我输入一个选项,然后第二次跳过输入,直接转到开关的默认情况。 然后第三次它就会允许我输入。不明白为什么。 任何帮助将不胜感激。
我在 JavaScript 中有一个 for 循环,它会定期跳过间隔,但我无法确定原因。 console.log(parseInt($('input.num-to-add').val())); num
我正在 JasperSoft 中填写参数。在我的报告中我有参数:参数_1、参数_2、参数_3 int a; for (a = 0; a < headers.length; a++) {
我是一名优秀的程序员,十分优秀!