Crossdevice编码静态文件在浏览器中使用FFMPEGstream(分段h264?)

我在NodeJS中构build了一个媒体中心应用程序, (你可以在Github上查看: https : //github.com/jansmolders86/mediacenterjs )

我正在使用FFMPEG将本地(静态)电影转码为一个stream,然后发送到浏览器。

起初,我使用了Flash在浏览器中工作的h264,但我真的需要它在Android上工作(所以没有Flash),最好在Raspberry Pi上工作。

但是让它在所有设备上播放都让我绝对疯了!

我已经从无数小时阅读文章,教程和堆栈溢出post中得到了所有这些难题,这使我得出结论,我需要产生以下结论:

  • 使用video编解码器H264转码为MP4
  • 移动moovatom'-movflags'来制作MP4stream式传输
  • 将stream分段,Apple也可以播放stream。

但是没有办法。 每次我产生一系列FFMPEG设置,要么不工作,要么在某些设备上工作,而不是在所有设备上工作。

我的一些失败的尝试在哪里:

我的闪光尝试 – > 主要问题(不在IOS中运行):

'-y','-ss 0','-b 800k','-vcodec libx264','-acodec mp3'\ '-ab 128','-ar 44100','-bufsize 62000', '-maxrate 620k'\ metaDuration,tDuration,'-f flv 

我的HLS尝试 – > 主要问题(不在浏览器中运行):

  '-r 15','-b:v 128k','-c:v libx264','-x264opts level=41'\ '-threads 4','-s 640x480','-map 0:v','-map 0:a:0','-c:a mp3'\ '-b:a 160000','-ac 2','-f hls','-hls_time 10','-hls_list_size 6'\ '-hls_wrap 18','-start_number 1' 

我的MP4尝试 – > 主要问题(持续时间缩短,后面的部分video正在加速)

  '-y','-ss 0','-b 800k','-vcodec libx264','-acodec mp3'\ '-ab 128','-ar 44100','-bufsize 62000', '-maxrate 620k'\ metaDuration,tDuration,'-f mp4','-movflags','frag_keyframe+empty_moov' 

第二次MP4尝试: – > 主要问题(持续时间缩短,video后期正在加速)

  '-y','-vcodec libx264','-pix_fmt yuv420p','-b 1200k','-flags +loop+mv4'\ '-cmp 256','-partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8'\ '-me_method hex','-subq 7','-trellis 1','-refs 5','-bf 3','-coder 1'\ '-me_range 16','-g 150','-keyint_min 25','-sc_threshold 40'\ '-i_qfactor 0.71','-acodec mp3','-qmin 10','-qdiff 4','-qmax 51'\ '-ab 128k','-ar 44100','-threads 2','-f mp4','-movflags','frag_keyframe+empty_moov']) 

以下是使用这些设置运行的FFMPEG日志的示例:

  file conversion error ffmpeg version N-52458-gaa96439 Copyright (c) 2000-2013 the FFmpeg developers built on Apr 24 2013 22:19:32 with gcc 4.8.0 (GCC) configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --e nable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable -libgsm --enable-libilbc --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --ena ble-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwola me --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enabl e-libxvid --enable-zlib libavutil 52. 27.101 / 52. 27.101 libavcodec 55. 6.100 / 55. 6.100 libavformat 55. 3.100 / 55. 3.100 libavdevice 55. 0.100 / 55. 0.100 libavfilter 3. 60.101 / 3. 60.101 libswscale 2. 2.100 / 2. 2.100 libswresample 0. 17.102 / 0. 17.102 libpostproc 52. 3.100 / 52. 3.100 [avi @ 02427900] non-interleaved AVI Guessed Channel Layout for Input Stream #0.1 : mono Input #0, avi, from 'C:/temp/the avengers.avi': Duration: 00:00:34.00, start: 0.000000, bitrate: 1433 kb/s Stream #0:0: Video: cinepak (cvid / 0x64697663), rgb24, 320x240, 15 tbr, 15 tbn, 15 tbc Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, mono, u8, 176 kb/s Please use -b:a or -b:v, -b is ambiguous [libx264 @ 02527c60] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX [libx264 @ 02527c60] profile High, level 2.0 [libx264 @ 02527c60] 264 - core 130 r2274 c832fe9 - H.264/MPEG-4 AVC codec - Copyleft 2003-2013 - http://www.videolan.org/x26 4.html - options: cabac=1 ref=5 deblock=1:0:0 analyse=0x3:0x133 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=2 lookahead_threads=1 sliced_th reads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 we ightb=1 open_gop=0 weightp=2 keyint=150 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=abr mbtree=1 bitrate=120 0 ratetol=1.0 qcomp=0.60 qpmin=10 qpmax=51 qpstep=4 ip_ratio=1.41 aq=1:1.00 Output #0, mp4, to 'pipe:1': Metadata: encoder : Lavf55.3.100 Stream #0:0: Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 320x240, q=10-51, 1200 kb/s, 15360 tbn, 15 tbc Stream #0:1: Audio: mp3 (i[0][0][0] / 0x0069), 44100 Hz, mono, s16p, 128 kb/s Stream mapping: Stream #0:0 -> #0:0 (cinepak -> libx264) Stream #0:1 -> #0:1 (pcm_u8 -> libmp3lame) Press [q] to stop, [?] for help frame= 106 fps=0.0 q=10.0 size= 1kB time=00:00:06.94 bitrate= 1.4kbits/s frame= 150 fps=149 q=14.0 size= 1kB time=00:00:09.87 bitrate= 1.0kbits/s frame= 191 fps=126 q=16.0 size= 1kB time=00:00:12.61 bitrate= 0.8kbits/s frame= 244 fps=121 q=16.0 size= 2262kB time=00:00:16.14 bitrate=1147.6kbits/s frame= 303 fps=120 q=14.0 size= 2262kB time=00:00:20.08 bitrate= 922.2kbits/s frame= 354 fps=117 q=15.0 size= 3035kB time=00:00:23.48 bitrate=1058.6kbits/s frame= 402 fps=113 q=15.0 size= 3035kB time=00:00:26.67 bitrate= 932.1kbits/s frame= 459 fps=113 q=16.0 size= 4041kB time=00:00:30.43 bitrate=1087.7kbits/s frame= 510 fps=103 q=2686559.0 Lsize= 5755kB time=00:00:33.93 bitrate=1389.3kbits/s video:5211kB audio:531kB subtitle:0 global headers:0kB muxing overhead 0.235111% [libx264 @ 02527c60] frame I:6 Avg QP:10.55 size: 25921 [libx264 @ 02527c60] frame P:245 Avg QP:12.15 size: 14543 [libx264 @ 02527c60] frame B:259 Avg QP:15.55 size: 6242 [libx264 @ 02527c60] consecutive B-frames: 6.1% 73.7% 14.7% 5.5% [libx264 @ 02527c60] mb I I16..4: 19.9% 6.2% 73.9% [libx264 @ 02527c60] mb P I16..4: 6.0% 0.2% 12.0% P16..4: 35.4% 9.6% 16.3% 7.0% 5.6% skip: 7.8% [libx264 @ 02527c60] mb B I16..4: 0.7% 0.0% 4.3% B16..8: 27.6% 17.2% 17.0% direct:17.3% skip:15.9% L0:39.4% L1:43.2% BI:17.4% [libx264 @ 02527c60] final ratefactor: 11.41 [libx264 @ 02527c60] 8x8 transform intra:1.6% inter:4.0% [libx264 @ 02527c60] coded y,uvDC,uvAC intra: 93.0% 97.0% 94.9% inter: 58.4% 58.7% 50.6% [libx264 @ 02527c60] i16 v,h,dc,p: 15% 26% 54% 5% [libx264 @ 02527c60] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 16% 17% 39% 4% 4% 3% 1% 6% 9% [libx264 @ 02527c60] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 28% 34% 21% 4% 2% 2% 2% 2% 5% [libx264 @ 02527c60] i8c dc,h,v,p: 51% 24% 19% 6% [libx264 @ 02527c60] Weighted P-Frames: Y:4.1% UV:1.2% [libx264 @ 02527c60] ref P L0: 68.2% 9.8% 11.0% 5.6% 4.6% 0.8% 0.0% [libx264 @ 02527c60] ref B L0: 87.7% 8.0% 3.9% 0.4% [libx264 @ 02527c60] ref B L1: 97.8% 2.2% [libx264 @ 02527c60] kb/s:1255.36 

最后这是我的节点代码激发了FFMPEG。 (我使用模块Fluent-ffmpeg: https : //github.com/schaermu/node-fluent-ffmpeg )

  var proc = new ffmpeg({ source: movie, nolog: true, timeout:15000}) .addOptions(['-r 15','-b:v 128k','-c:v libx264','-x264opts level=41','-threads 4','-s 640x480','-map 0:v','-map 0:a:0','-c:a mp3','-b:a 160000','-ac 2','-f hls','-hls_time 10','-hls_list_size 6','-hls_wrap 18','-start_number 1 stream.m3u8']) .writeToStream(res, function(retcode, error){ if (!error){ console.log('file has been converted succesfully',retcode .green); }else{ console.log('file conversion error',error .red); } }); 

所以总结这个很长的代码重要的问题:

我希望这不会作为一个懒惰的请求,但可以有人向我展示/向我解释哪些FFMPEG设置可以/应该在所有平台(现代浏览器,Android和iOS)上生成一个静态文件stream,我可以发送到一个HTML5播放器。

[编辑]我需要什么,如果一个普通的选项不可用

如果这是不可能的,因为一些职位可能build议,我很想看到一套FFMPEG设置,就mp4stream媒体而言,正确完成工作。 (例如编码stream式mp4)。

streammp4需要以下

  • 转移moovAtom
  • 它需要是h264

非常感谢您的帮助!

没有可以在每个设备和浏览器上播放的格式。 HTML5让我们更加接近,但格式和编解码器仍然存在争议。 我在Zencoder的朋友们有一个新的博客文章博客文章( HERE )来解决这个问题。

编辑:你问了更多的细节。 再次,这取决于你想要的目标平台。 我将在这里介绍一对夫妇。

这应该在所有支持h.264编解码器的现代浏览器上播放。 它也应该玩iPhone4及以上版本:

 ffmpeg -i ~/Dropbox/Test\ Content/bigbuckbunny/bigbuckbunny_1500.mp4 -vcodec libx264 -profile:v main -b:v 512k -s 1280x720 -r:v 30 -acodec libfdk_aac -b:a 128k -movflags faststart -y movie1.mp4 

iPhone 3gs不支持主configuration文件,其最大支持的分辨率是640×480。 这个命令将编码这个较旧的设备。

 ffmpeg -i ~/Dropbox/Test\ Content/bigbuckbunny/bigbuckbunny_1500.mp4 -vcodec libx264 -profile:v baseline -b:v 512k -s 640x432 -r:v 30 -acodec libfdk_aac -b:a 128k -movflags faststart -y movie2.mp4 

我编码了一些示例文件,并在这里创build了一个网页: http : //szatmary.org/stackoverflow/18758133/

HTML看起来像这样:

 <!DOCTYPE html> <html> <body> <br>ffmpeg -i ~/Dropbox/Test\ Content/bigbuckbunny/bigbuckbunny_1500.mp4 -vcodec libx264 -profile:v main -b:v 512k -s 1280x720 -r:v 30 -acodec libfdk_aac -b:a 128k -movflags faststart -y movie1.mp4<br> <video controls> <source src="movie1.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <br>ffmpeg -i ~/Dropbox/Test\ Content/bigbuckbunny/bigbuckbunny_1500.mp4 -vcodec libx264 -profile:v baseline -b:v 512k -s 640x432 -r:v 30 -acodec libfdk_aac -b:a 128k -movflags faststart -y movie2.mp4<br> <video controls> <source src="movie2.mp4" type="video/mp4"> Your browser does not support the video tag. </video> </body> </html> 

这里的命令分解成每个元素的含义:

命令+input文件(应该是显而易见的):

 ffmpeg -i ~/Dropbox/Test\ Content/bigbuckbunny/bigbuckbunny_1500.mp4 

使用libx264来编码video:

 -vcodec libx264 

将h.264configuration文件设置为主。 基线将允许在较旧的设备上播放,但您将牺牲一点质量:

 -profile:v main 

将比特率设置为每秒512千比特。 根据可用带宽select一个值。 LAN / WiFi较高,3G / LTE较低

 -b:v 512k 

将video缩放到720p分辨率(又取决于目标平台)

 -s 1280x720 

以每秒30帧的速度进行编码:

 -r:v 30 

使用libfdk_aac来编码audio。 或者,如果你想mp3,使用libmp3lame。 AAC强烈推荐。 它在ios上有更好的支持,能够产生更高质量的audio:

 -acodec libfdk_aac 

将audio比特率设置为每秒128千比特。 你也可以调整这个带宽。 与AAC你可能会低至32K

 -b:a 128k 

将audio采样率设置为每秒48000个采样。 如果使用mp3,请为ios执行44100

 -r:a 48000 

这告诉ffmpeg把moovprimefaces放在mp4文件的开头。

 -movflags faststart 

输出文件(-y告诉ffmpeg它可以覆盖文件而不询问)

 -y movie1.mp4 

据我所知,你不会find一个适用于每个设备的设置。 我build议您检查用户代理,然后针对不同的设备使用不同的设置。 这样你也可以使用设备优化的设置。

我正在考虑2个解决方法来启用search。 我假设,像我一样,你不想存储预先转码的文件。

第一个只是从浏览器中寻找。 使用自定义的时间线控制,并寻求更改videosrc到一个URL,包括所需的开始时间,并将其传递给ffmpeg。 当然,这完全破坏了浏览器预取。 我在我的项目中实现了这一点,它工作正常。

第二个选项是更多的技术,我不知道如何做到这一点。 这个想法是提前转码所有可用的video,提取moovprimefaces,将其保存到磁盘并在stream式传输时手动写入。 这似乎很难但不是不可能的。