所以从我的网络服务器,我想使用FFMPEG转码一个媒体文件,以使用HTML< audio>或< video>标签。足够容易吗
当HTTP客户端请求转换的文件时,转换将需要实时进行。理想情况下,文件将被转发回HTTP客户端,因为它正在进行转码(而不是最终转换),因为在任何数据开始发回之前,这可能需要一段时间。
这是很好的,除了在今天的浏览器中,HTML5音频或视频标签使用Range标头在多个HTTP请求中请求媒体文件。 See this question for details。
在上面链接的问题中,您可以看到Safari请求文件的奇怪块,包括结尾几个字节。这造成了一个问题,Web服务器必须等待转换完成,以便传递文件的最终字节以符合Range请求。
所以我的问题是,我的思路是对吗?是否有更好的方式将转码内容提供给< audio>或< video>标签不会涉及等待整个转换完成?提前致谢!
解决方法
我最近遇到了同样的问题,因为我想把我的图书馆服务于浏览器。令人惊讶的是,通过ffmpeg发送流并在飞行中传送的想法效果非常好。主要问题是支持寻求…
以下,您在Python中使用Flask找到代码sniplet来解决问题:
@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"})
那么我们需要一个函数来返回持续时间:
@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:
<!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找到。
德罗