PHP 流媒体 MP3

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2358253/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:10:22  来源:igfitidea点击:

PHP Streaming MP3

phpmp3headerfilestreamreadfile

提问by Yuval Karmi

I have a very similar situation to the person who asked: Can I serve MP3 files with PHP?Basically I am trying to protect mp3 files from direct download, so users have to go through php to get authenticated first. Here's my code:

我和问的人有非常相似的情况: 我可以用 PHP 提供 MP3 文件吗?基本上,我试图保护 mp3 文件免于直接下载,因此用户必须先通过 php 进行身份验证。这是我的代码:

header('Content-type: audio/mpeg');
header('Content-length: ' . filesize($file));
header('X-Pad: avoid browser bug');
Header('Cache-Control: no-cache');
header("Content-Transfer-Encoding: binary"); 
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
readfile($file);

Here's my problem: The file only plays a very small chunk of the beginning (via Quicktime in the browser) and then stops - Quicktime seems to think the length of the file is only as long as the chunk it managed to download. When I reload - it plays a slightly larger chunk - whatever it managed to download up to that point.

这是我的问题:文件只播放开头的一小部分(通过浏览器中的 Quicktime)然后停止 - Quicktime 似乎认为文件长度与它设法下载的块一样长。当我重新加载时 - 它会播放一个稍大的块 - 无论它在那个时候设法下载。

Is that a problem in the headers I am sending? How would I stream such a file? Is it a problem if an swf is reading from that file?

这是我发送的标题中的问题吗?我将如何流式传输这样的文件?如果 swf 正在从该文件中读取,是否有问题?

Thanks!

谢谢!



Thank you guys for all the answers. Although none of these things were exactly what solved the problem, many of them sent me in the right direction. Much appreciated. For the full solution see my answer below

谢谢大家的回答。尽管这些都不是解决问题的真正原因,但其中许多都让我朝着正确的方向前进。非常感激。有关完整的解决方案,请参阅下面的我的答案

采纳答案by Yuval Karmi

Here's what did the trick.

这就是诀窍。

$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/protected_content";
$filename = $_GET['file'];
$file = $dir."/".$filename;

$extension = "mp3";
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";

if(file_exists($file)){
    header('Content-type: {$mime_type}');
    header('Content-length: ' . filesize($file));
    header('Content-Disposition: filename="' . $filename);
    header('X-Pad: avoid browser bug');
    header('Cache-Control: no-cache');
    readfile($file);
}else{
    header("HTTP/1.0 404 Not Found");
}

回答by outis

You can try HTTP chunking. Set the "Transfer-Encoding" header to "chunked", then output the size of each chunk before sending it. End each chunk size and chunk with a CRLF.

您可以尝试HTTP 分块。将“Transfer-Encoding”头设置为“chunked”,然后在发送之前输出每个chunk的大小。以 CRLF 结束每个块大小和块。

For anything more complex, I recommend using a streaming server, such as Icecast.

对于更复杂的事情,我建议使用流媒体服务器,例如Icecast

回答by mattbasta

Two things stand out:

有两点很突出:

  1. You've got a Content-Lengthset. If you server is set to automatically gzip your output, this can mess with things. Try turning off Content-Lengthand see if that fixes it.
  2. You've got about a thousand Content-Types set. Since it's Mp3 that you're serving, just use audio/mpeg. You can effectively get rid of the whole last header()command. It's easy to get carried away with HTTP headers.
  1. Content-Length有一套。如果您的服务器设置为自动 gzip 输出,这可能会造成混乱。尝试关闭Content-Length,看看是否可以解决它。
  2. 你有大约一千Content-Type套。由于您提供的是 Mp3,因此只需使用audio/mpeg. 您可以有效地摆脱整个最后一个header()命令。很容易被 HTTP 标头带走。

Try it out and let us know how it goes!

试试看,让我们知道它是怎么回事!

回答by roman

if your server is running on apache or lighty, i would suggest you look into x-sendfile

如果您的服务器在 apache 或 lighty 上运行,我建议您查看 x-sendfile

http://tn123.ath.cx/mod_xsendfile/

http://tn123.ath.cx/mod_xsendfile/

this allows you to handle authentication in your php application, but let's your webserver handle the transmission of the file. the performance improvement you gain should be a nice additional benefit

这允许您在 php 应用程序中处理身份验证,但让您的网络服务器处理文件的传输。您获得的性能改进应该是一个不错的额外好处

回答by Roozbeh15

Remove header("Content-Transfer-Encoding: binary");And you'll be set!

删除header("Content-Transfer-Encoding: binary");你会被设置!

回答by nvvetal

For these solution you also need to configure xsendfile in apache (mod_xsendfile) or nginx HttpSecureLinkModule - they will give you exact mp3, so browser will play it correctly

对于这些解决方案,您还需要在 apache (mod_xsendfile) 或 nginx HttpSecureLinkModule 中配置 xsendfile - 它们将为您提供准确的 mp3,因此浏览器将正确播放

回答by Tormy Van Cool

Applying all these solutions, which are valid to hide the original path and filename, unfortunately doesn't prevent from unauthorized download. Indeed the client (on my case: Chrome) downloads the file.

不幸的是,应用所有这些有效隐藏原始路径和文件名的解决方案并不能阻止未经授权的下载。事实上,客户端(就我而言:Chrome)下载文件。

Here the lines I put on my server:

这是我放在服务器上的行:

<?php
$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/mp3";
$filename = $_GET['file'];
$file = $dir."/".$filename;

$extension = "mp3";
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";

if(file_exists($file)){
    header('Content-type: {$mime_type}');
    header('Content-length: ' . filesize($file));
    header("Content-Transfer-Encoding: binary"); 
    header('Content-Disposition: filename="' . $filename);
    header('X-Pad: avoid browser bug');
    header('Cache-Control: no-cache');
    readfile($file);
}else{
    header("HTTP/1.0 404 Not Found");
}
?>

with or without the line

有或没有线

    header("Content-Transfer-Encoding: binary"); 

the final result doesn't change The directory /mp3 is located into

最终结果不会改变目录/mp3位于

/home/myuser/

(thus /home/myuser/mp3) and the public HTML directory is

(因此 /home/myuser/mp3)和公共 HTML 目录是

/home/myuser/public_html

thus calling my domain and giving

因此调用我的域并给予

/player.php?file=music.mp3

it downloads a file called music.mp3 with all the original content.

它会下载一个名为 music.mp3 的文件,其中包含所有原始内容。