Estoy creando una aplicación NodeJS que convierte un archivo de video estático en un video que se transmite y se envía a un cliente (iPad o navegador) sobre la marcha (usando el módulo fluent-ffmpeg).
Todo está configurado y todo lo que necesito ahora es configurar ffmpeg correctamente. Pero tengo muchos problemas con ffmpeg. Al principio construí una transmisión flash (flv con códec lib264 que funcionó muy bien, pero por supuesto no funciona en el iPad).
Con mi configuración actual, escucho el audio de inmediato, pero la imagen comienza un par de segundos después. Luego, mi archivo de prueba de 30 segundos se ha comprimido a 3 segundos de imágenes de alta velocidad.
¿Cómo puedo configurar mi ffmpeg para que transmita el mp4 correctamente (en una pasada, por supuesto)? Parece que está transmitiendo h264 sin formato, si ese es el caso, ¿cómo puedo forzar el contenedor mp4? Pensé que estaba haciendo eso usando '-f mp4'
mis configuraciones correctas son:
'-crf 22','-c:v libx264','-f mp4','-movflags','faststart+frag_keyframe'
También he intentado:
'-r 30','-crf 30','-analyzeduration 0','-probesize 1000','-rc_lookahead 0','-fflags nobuffer','-g 75','-ss 0','-threads 0','-vcodec libx264','-qcomp 0.6','-qmin 10','-qmax 51','-qdiff 4','-b:v 400k','-maxrate 400k','-bufsize 800k','-acodec mp3','-ab 192k','-ar 44100','-tune zerolatency','-f mp4','-movflags','faststart+frag_keyframe'
Como puede ver por la cantidad de opciones que he probado, me estoy desesperando bastante. Básicamente solo estoy corriendo en la oscuridad.
No creo que importe mucho, pero estos son mis encabezados de solicitud:
res.writeHead(200, {
'Content-Type':'video/mp4',
'Content-Length':stat.size,
'Content-Range':'bytes '+start+'-'+end+'/'+stat.size,
'Transfer-Encoding':'chunked'
});
Registro 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 --enable-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 --enable-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 --enable-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
Input #0, avi, from 'C:/temp/avatar.avi':
Metadata:
encoder : Nandub v1.0rc2
Duration: 00:01:09.78, start: 0.000000, bitrate: 1517 kb/s
Stream #0:0: Video: msmpeg4v3 (DIV3 / 0x33564944), yuv420p, 640x352, 23.98 tbr, 23.98 tbn, 23.98 tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 48000 Hz, stereo, s16p, 222 kb/s
[libx264 @ 0218d480] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0218d480] profile High, level 3.0
[libx264 @ 0218d480] 264 - core 130 r2274 c832fe9 - H.264/MPEG-4 AVC codec - Copyleft 2003-2013 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 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=12 lookahead_threads=2 sliced_threads=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 w
eightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=23 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=22.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 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, 640x352, q=-1--1, 11988 tbn, 23.98 tbc
Stream #0:1: Audio: aac ([64][0][0][0] / 0x0040), 48000 Hz, stereo, s16, 128 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (msmpeg4 -> libx264)
Stream #0:1 -> #0:1 (mp3 -> libvo_aacenc)
Press [q] to stop, [?] for help
frame= 103 fps=0.0 q=27.0 size= 0kB time=00:00:04.70 bitrate= 0.1kbits/s
frame= 162 fps=161 q=27.0 size= 278kB time=00:00:07.15 bitrate= 317.9kbits/s
frame= 214 fps=141 q=27.0 size= 463kB time=00:00:09.33 bitrate= 406.3kbits/s
frame= 277 fps=137 q=27.0 size= 673kB time=00:00:11.95 bitrate= 461.3kbits/s
frame= 334 fps=132 q=27.0 size= 826kB time=00:00:14.32 bitrate= 472.5kbits/s
frame= 386 fps=127 q=27.0 size= 1061kB time=00:00:16.52 bitrate= 526.2kbits/s
frame= 428 fps=120 q=27.0 size= 1061kB time=00:00:18.27 bitrate= 475.9kbits/s
frame= 472 fps=116 q=27.0 size= 1061kB time=00:00:20.08 bitrate= 432.9kbits/s
frame= 525 fps=115 q=27.0 size= 1562kB time=00:00:22.30 bitrate= 573.7kbits/s
frame= 589 fps=116 q=27.0 size= 1804kB time=00:00:24.99 bitrate= 591.4kbits/s
frame= 690 fps=124 q=27.0 size= 1804kB time=00:00:29.19 bitrate= 506.2kbits/s
frame= 827 fps=136 q=27.0 size= 2191kB time=00:00:34.91 bitrate= 514.1kbits/s
frame= 921 fps=140 q=27.0 size= 2540kB time=00:00:38.81 bitrate= 536.1kbits/s
frame= 1015 fps=143 q=27.0 size= 2540kB time=00:00:42.74 bitrate= 486.9kbits/s
frame= 1124 fps=148 q=27.0 size= 3531kB time=00:00:47.30 bitrate= 611.5kbits/s
frame= 1248 fps=154 q=27.0 size= 3727kB time=00:00:52.46 bitrate= 581.9kbits/s
frame= 1371 fps=160 q=27.0 size= 4251kB time=00:00:57.58 bitrate= 604.7kbits/s
frame= 1516 fps=167 q=27.0 size= 4684kB time=00:01:03.62 bitrate= 603.0kbits/s
frame= 1632 fps=170 q=27.0 size= 4932kB time=00:01:08.46 bitrate= 590.1kbits/s
frame= 1673 fps=167 q=2686559.0 Lsize= 5507kB time=00:01:09.76 bitrate= 646.6kbits/s
video:4385kB audio:1091kB subtitle:0 global headers:0kB muxing overhead 0.582195%
[libx264 @ 0218d480] frame I:17 Avg QP:18.90 size: 11501
[libx264 @ 0218d480] frame P:1467 Avg QP:21.41 size: 2825
[libx264 @ 0218d480] frame B:189 Avg QP:24.42 size: 788
[libx264 @ 0218d480] consecutive B-frames: 84.5% 1.0% 1.4% 13.2%
[libx264 @ 0218d480] mb I I16..4: 21.5% 75.6% 2.9%
[libx264 @ 0218d480] mb P I16..4: 1.0% 2.8% 0.2% P16..4: 39.6% 13.7% 8.2% 0.0% 0.0% skip:34.6%
[libx264 @ 0218d480] mb B I16..4: 0.1% 0.3% 0.1% B16..8: 37.3% 2.6% 0.4% direct: 0.8% skip:58.4% L0:44.0% L1:51.7% BI: 4.3%
[libx264 @ 0218d480] 8x8 transform intra:70.8% inter:82.9%
[libx264 @ 0218d480] coded y,uvDC,uvAC intra: 58.7% 53.9% 12.8% inter: 20.2% 19.7% 0.4%
[libx264 @ 0218d480] i16 v,h,dc,p: 62% 16% 9% 13%
[libx264 @ 0218d480] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 27% 14% 30% 3% 5% 6% 4% 5% 4%
[libx264 @ 0218d480] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 34% 13% 11% 4% 10% 11% 7% 6% 3%
[libx264 @ 0218d480] i8c dc,h,v,p: 44% 19% 33% 4%
[libx264 @ 0218d480] Weighted P-Frames: Y:0.1% UV:0.0%
[libx264 @ 0218d480] ref P L0: 69.0% 16.7% 10.2% 4.0% 0.0%
[libx264 @ 0218d480] ref B L0: 86.1% 10.0% 3.9%
[libx264 @ 0218d480] ref B L1: 92.9% 7.1%
[libx264 @ 0218d480] kb/s:514.67
Mi comando nodejs exacto con los casos de prueba que he usado (que están comentados):
, proc = new ffmpeg({
source: movie,
nolog: true,
timeout:15000
})
.addOptions(['-crf 22','-c:v libx264','-f mp4','-movflags','faststart+frag_keyframe'])
//.addOptions(['-threads 0', '-i_qfactor 0.71', '-qcomp 0.6', '-qmin 10', '-qmax 63', '-qdiff 4', '-trellis 0', '-vcodec libx264', '-s 640x360', '-b:v 1000k', '-b:a 56k','-ar 22050','-f mp4','-movflags','faststart+frag_keyframe'])
//.addOptions(['-r 30','-crf 30','-analyzeduration 0','-probesize 1000','-rc_lookahead 0','-fflags nobuffer','-g 75','-ss 0','-threads 0','-vcodec libx264','-qcomp 0.6','-qmin 10','-qmax 51','-qdiff 4','-b:v 400k','-maxrate 400k','-bufsize 800k','-acodec mp3','-ab 192k','-ar 44100','-tune zerolatency',metaDuration,tDuration,'-f mp4','-movflags','faststart+frag_keyframe'])
.writeToStream(res, function(retcode, error){
if (!error){
console.log('file has been converted succesfully',retcode .green);
}else{
console.log('file conversion error',error .red);
}
});
Mi reproductor frontend es un reproductor HTML5 básico con videoJS en la parte superior (por temas y capacidad de control).
<video id="player" class="video-js vjs-default-skin" controls preload="both" width="100%" height="100%"><source src="'+url+'" type="video/mp4"></video>
fuente
Respuestas:
¿Comprobó que la velocidad de fotogramas del video original coincide con sus otras configuraciones? Además, el video fuente si tiene 48kHz para comenzar, cuando va a codificar podría causar el cambio que está viendo cuando intenta hacer que la salida sea 44.1kHz. Asegúrese de que el archivo que entra también sea 44.1
fuente
La respuesta puede llegar un poco tarde, pero ¿intentó usar la opción '-re'?
Si no lo usa, intenta transmitir el video al destino lo más rápido posible.
Con -re lees el archivo a su velocidad de fotogramas nativa y, por lo tanto, también se transmite a la velocidad de reproducción del video.
fuente