首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >HTML5 <音频>/<视频>和FFMPEG实时转码

HTML5 <音频>/<视频>和FFMPEG实时转码
EN

Stack Overflow用户
提问于 2010-09-04 05:11:23
回答 3查看 15.7K关注 0票数 21

因此,在我的web服务器上,我想使用FFMPEG对媒体文件进行代码转换,以便与HTML <audio><video>标签一起使用。很简单,对吧?

转换需要在HTTP客户端请求转换后的文件时实时进行。理想情况下,文件应该在代码转换时流回HTTP客户端(而不是在代码转换结束后,因为这可能需要一段时间才能开始发送回任何数据)。

这很好,除了在今天的浏览器中,HTML5音频或视频标签使用Range头在多个HTTP请求中请求媒体文件。See this question for details

在上面链接的问题中,您可以看到Safari请求奇怪的文件块,包括结尾的几个字节。这带来了一个问题,即web服务器将不得不等待转换完成,以便传递文件的最后字节以符合Range请求。

所以我的问题是,我的思路是正确的吗?有没有一种更好的方法来将代码转换内容传递到<audio><video>标签,而不需要等待整个转换完成?提前感谢!

EN

回答 3

Stack Overflow用户

发布于 2014-05-08 13:26:41

我最近遇到了同样的问题,因为我想为浏览器提供我的库。令人惊讶的是,通过ffmpeg发送流并即时交付的想法运行得很好。主要的问题是支持寻求……

下面,你可以使用Flask在Python中找到代码片段来解决这个问题:

我们需要一个函数来流式传输内容:

代码语言:javascript
复制
@app.route('/media/<path:path>.ogv')
def media_content_ogv(path):
    d= os.path.abspath( os.path.join( config.media_folder, path ) )
    if not os.path.isfile( d ): abort(404)
    start= request.args.get("start") or 0
    def generate():
        cmdline= list()
        cmdline.append( config.ffmpeg )
        cmdline.append( "-i" )
        cmdline.append( d );
        cmdline.append( "-ss" )
        cmdline.append( str(start) );
        cmdline.extend( config.ffmpeg_args )
        print cmdline
        FNULL = open(os.devnull, 'w')
        proc= subprocess.Popen( cmdline, stdout=subprocess.PIPE, stderr=FNULL )
        try:
            f= proc.stdout
            byte = f.read(512)
            while byte:
                yield byte
                byte = f.read(512)
        finally:
            proc.kill()

    return Response(response=generate(),status=200,mimetype='video/ogg',headers={'Access-Control-Allow-Origin': '*', "Content-Type":"video/ogg","Content-Disposition":"inline","Content-Transfer-Enconding":"binary"})

然后我们需要一个函数来返回持续时间:

代码语言:javascript
复制
@app.route('/media/<path:path>.js')
def media_content_js(path):
    d= os.path.abspath( os.path.join( config.media_folder, path ) )
    if not os.path.isfile( d ): abort(404)
    cmdline= list()
    cmdline.append( config.ffmpeg )
    cmdline.append( "-i" )
    cmdline.append( d );
    duration= -1
    FNULL = open(os.devnull, 'w')
    proc= subprocess.Popen( cmdline, stderr=subprocess.PIPE, stdout=FNULL )
    try:
        for line in iter(proc.stderr.readline,''):
            line= line.rstrip()
            #Duration: 00:00:45.13, start: 0.000000, bitrate: 302 kb/s
            m = re.search('Duration: (..):(..):(..)\...', line)
            if m is not None: duration= int(m.group(1)) * 3600 + int(m.group(2)) * 60 + int(m.group(3)) + 1
    finally:
        proc.kill()

    return jsonify(duration=duration)

最后,我们使用videojs将其嵌入HTML5:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <link href="//vjs.zencdn.net/4.5/video-js.css" rel="stylesheet">
    <script src="//vjs.zencdn.net/4.5/video.js"></script>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
<body>
    <video id="video" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264">
    </video>
    <script>
        var video= videojs('video');
        video.src("media/testavi.avi.ogv");

        // hack duration
        video.duration= function() { return video.theDuration; };
        video.start= 0;
        video.oldCurrentTime= video.currentTime;
        video.currentTime= function(time) 
        { 
            if( time == undefined )
            {
                return video.oldCurrentTime() + video.start;
            }
            console.log(time)
            video.start= time;
            video.oldCurrentTime(0);
            video.src("media/testavi.avi.ogv?start=" + time);
            video.play();
            return this;
        };

        $.getJSON( "media/testavi.avi.js", function( data ) 
        {
            video.theDuration= data.duration;
        });
    </script>
</body>

https://github.com/derolf/transcoder上可以找到一个有效的例子。

dero

票数 11
EN

Stack Overflow用户

发布于 2020-05-14 00:12:08

我知道这是一个老帖子,但如果有人发现它并需要帮助,我无论如何都会把它贴出来。

'user3612643‘答案是正确的,这解决了寻道问题。然而,这引入了一个新的问题。当前时间不再正确。要解决这个问题,我们必须复制原始的currentTime函数。

现在,每次video.js调用currentTime (没有参数)时,它都会调用oldCurrentTime,这是原始的currentTime函数。其余部分与‘user3612643’的答案相同(谢谢!)。这适用于最新的video.js (7.7.6)。

代码语言:javascript
复制
    video = videojs("video");
    video.src({
      src: 'http://localhost:4000/api/video/sdf',
      type: 'video/webm'
    });


     // hack duration
     video.duration= function() {return video.theDuration; };
     video.start= 0;

     // The original code for "currentTime"
     video.oldCurrentTime = function currentTime(seconds) {
      if (typeof seconds !== 'undefined') {
        if (seconds < 0) {
          seconds = 0;
        }

        this.techCall_('setCurrentTime', seconds);
        return;
      }
      this.cache_.currentTime = this.techGet_('currentTime') || 0;
      return this.cache_.currentTime;
    }

      // Our modified currentTime
     video.currentTime= function(time) 
     { 
         if( time == undefined )
         {
             return video.oldCurrentTime() + video.start;
         }
         video.start= time;
         video.oldCurrentTime(0);
         video.src({
           src: "http://localhost:4000/api/video/sdf?start=" + time,
           type: 'video/webm'
          });
         video.play();
         return this;
     };

     // Get the dureation of the movie
     $.getJSON( "http://localhost:4000/api/video/sdf/getDuration", function( data ) 
     {
         video.theDuration= data.duration;
     });
票数 0
EN

Stack Overflow用户

发布于 2011-08-12 04:21:36

这应该可以通过VLC来实现,我可以通过设置VLC来托管一个大的avi文件并将其转码为OGG,然后我的html5引用了这个流:

代码语言:javascript
复制
<source src="http://localhost:8081/stream.ogg">

它可以在vlc中进行转码,在我的chrome浏览器和我的android手机上渲染也很好,但我最终选择了一个different solution,而不是创建自己的webapp来托管我的媒体收藏和为所请求的文件创建流-我寻找并找不到一个已经存在的免费应用程序,它以我需要/喜欢的方式做到了这一点。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3639604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档