0

我目前正在制作一个 perl 脚本,它将文件转换为 webm/ogg/mp4 格式,然后将其发送回用户,但嵌入视频。除了我无法发送 EOF 之外,这一切都有效,因此 HTML5 视频播放器知道结尾是什么,因此他可以正确使用文件(比如转到特定时间,甚至知道文件何时结束(现在它只是停止但你不能再对视频做任何事情了。

开始代码:

elsif ($path =~ /^\/((\w|\d){11})\.webm$/ig) {
    print "HTTP/1.0 200 OK\r\n";
    $handler = \&resp_youtubemovie;
    $handler->($cgi,$1);

发送webm文件的功能

sub resp_youtubemovie {
    my $cgi = shift;
    my $youtubeID = shift;
    return if !ref $cgi;
    open(movie,"<$youtubeID.webm");
    local($/);
    $movie = <movie>;
    close(movie);
    print "Content-type: movie/webm\n";
    print $movie;
}

我已经尝试过使用 while 循环和缓冲区,但这也不起作用,我还尝试将 HTTP 状态代码更改为 206 Partial Content,因为我对其他一些视频流网站使用了它,但它没有事情。那么有人知道如何打开电影文件并正确流式传输吗?

4

2 回答 2

3

无需手动执行此操作,Dancer之类的框架可以解决此问题。这将为您省去很多很多很多的麻烦。它还允许您利用Plack/PSGI 强力胶,它可以为您确定如何与 Web 服务器通信。

use Dancer;

get qr{/(\w{11}\.webm)$}i => sub {
    my($video_file) = splat;

    return send_file(
        $video_file,
        streaming => 1,
    );
}

使用Dancer 路由,您应该能够很容易地调整现有代码,特别是如果它与各种路径匹配的 if/elsif 很大。Dancer 在让简单的事情变得简单方面做得非常好,如果您需要,它还可以让您对确切的 HTTP 响应进行大量控制。

一些笔记...

  • webm的内容类型video/webm可能是您问题的根源。舞者应该做对了。如果不是,您可以明确告诉send_file内容类型。

  • (\w|\d){11}写得更好,\w{11}因为\w包括\d

于 2013-01-26T20:50:03.277 回答
2

您必须使用 206 Partial Content HTTP 状态并且还必须发送:

  • Accept-Range: bytes头。
  • 一个Content-Range: 0-2048/123456标头,您在其中发送内容的开始和结束字节索引,后跟内容的总字节长度。客户端将在请求标头中向您发送它想要的字节范围。客户端可能会在单个请求中发送多个字节范围,在这种情况下,您还需要发送具有多部分字边界的内容。

Finally, to get back to your question, if the client requests a byte range that isn't satisfiable then you send a 416 HTTP status and close the connection.

于 2013-01-26T22:27:16.413 回答