O conteúdo audiovisual perde a sincronização

1

Eu tenho um arquivo de vídeo .mp4 que veio de um .avi não compactado capturado de uma webcam por meio de emgu . O emgu videoWriter está definido como 30fps , mesmo que o vídeo real fps seja possivelmente menor, por exemplo, 29fps . O comando usado para compactar o .avi é:

Comando de compactação:

fmpeg -i uncompresedvideo.avi -v quiet -stats -nostdin -c:v libx264 -crf 1 -preset veryfast -maxrate 500k -bufsize 1835k vid.mp4

A saída de compactação de vídeo é:

ffmpeg version N-82060-g0cfd6cc Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 32.100 / 55. 32.100
  libavcodec     57. 63.103 / 57. 63.103
  libavformat    57. 52.100 / 57. 52.100
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 64.100 /  6. 64.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  2.100 /  2.  2.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, avi, from 'C:\....\uncompresedvideo.avi':
  Metadata:
    encoder         : Lavf56.36.100
  Duration: 00:02:50.27, start: 0.000000, bitrate: 110597 kb/s
    Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, 110613 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc
[libx264 @ 0000000002636460] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[libx264 @ 0000000002636460] profile High, level 3.0
[libx264 @ 0000000002636460] 264 - core 148 r2721 72d53ab - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=6 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 weightb=1 open_gop=0 weightp=1 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=crf mbtree=1 crf=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=500 vbv_bufsize=1835 crf_max=0.0 nal_hrd=none filler=0 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'C:\....\vid.mp4':
  Metadata:
    encoder         : Lavf57.52.100
    Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x480, q=-1--1, 30 fps, 15360 tbn, 30 tbc
    Metadata:
      encoder         : Lavc57.63.103 libx264
    Side data:
      cpb: bitrate max/min/avg: 500000/0/0 buffer size: 1835000 vbv_delay: -1
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))  

Além dessa gravação de vídeo, tenho um arquivo .wav que veio de um dispositivo diferente. Estou tentando sincronizá-los com o seguinte comando:

ffmpeg.exe -i vid.mp4 -r 30 -i audio.wav -ar 16000 -map 0:0 -map 1:0 -vcodec copy -acodec aac -shortest output.mp4

A saída do comando synch é:

ffmpeg version N-82060-g0cfd6cc Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 5.4.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2 --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-libebur128 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 32.100 / 55. 32.100
  libavcodec     57. 63.103 / 57. 63.103
  libavformat    57. 52.100 / 57. 52.100
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 64.100 /  6. 64.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  2.100 /  2.  2.100
  libpostproc    54.  0.100 / 54.  0.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'audio.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.52.100
  Duration: 00:02:50.27, start: 0.000000, bitrate: 507 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480, 504 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
Guessed Channel Layout for Input Stream #1.0 : mono
Input #1, wav, from 'audio.wav':
  Duration: 00:02:52.29, bitrate: 512 kb/s
    Stream #1:0: Audio: pcm_f32le ([3][0][0][0] / 0x0003), 16000 Hz, mono, flt, 512 kb/s
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.52.100
    Stream #0:0(und): Video: h264 (High) ([33][0][0][0] / 0x0021), yuv420p, 640x480, q=2-31, 504 kb/s, 30 fps, 30 tbr, 15360 tbn, 15360 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1: Audio: aac (LC) ([64][0][0][0] / 0x0040), 16000 Hz, mono, fltp, 69 kb/s
    Metadata:
      encoder         : Lavc57.63.103 aac
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #1:0 -> #0:1 (pcm_f32le (native) -> aac (native))
Press [q] to stop, [?] for help
frame= 5108 fps=1316 q=-1.0 Lsize=   11735kB time=00:02:52.28 bitrate= 558.0kbits/s speed=44.4x
video:10486kB audio:1151kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.836344%
[aac @ 00000000026977c0] Qavg: 65093.531

Gostaria de mencionar que o áudio e o vídeo têm um começo comum. Enquanto o conteúdo audiovisual tem boa sincronização no início, a sincronização é perdida no final do registro. Você poderia por favor fazer uma sugestão sobre o que está acontecendo?

Sua ajuda é muito apreciada, obrigado.

    
por Darkmoor 22.03.2017 / 10:38

1 resposta

1

Acho que o problema é que o seu vídeo de entrada já tem timestamps errados devido à forma como foi codificado. Eu entendo que o vídeo da webcam original estava produzindo quadros de comprimento variável (isto é, um vídeo de taxa de quadros variável), mas um arquivo AVI não compactado pode armazenar apenas quadros de comprimento constante .

Assim, lendo esse arquivo AVI (ou qualquer arquivo MP4 comprimido subseqüentemente), o ffmpeg assumirá que é um vídeo com taxa de quadros constante. Isso leva à "construção" de assincronia ao longo do tempo, já que os registros de data e hora em seu AVI / MP4 têm compensações constantes. O ffmpeg não pode consertar isso para você, porque os timestamps de entrada já estão incorretos. Em outras palavras, suponho que o videoWriter ao qual você se refere criou um vídeo com taxa de quadros constante a partir de uma taxa de quadros variável, criando timestamps incorretos. Sem saber quando ou como essa taxa de quadros mudou, não é possível corrigir os registros de data e hora.

Sua única opção seria gerar novamente o fluxo de vídeo da webcam com um contêiner que suporte taxa de quadros variável (como MKV ou MP4 / MOV). Em seguida, qualquer conversão subsequente pode sincronizar o conteúdo com um fluxo de áudio. Mas como esse feed da webcam provavelmente está ativo, não há como voltar atrás. Além disso, eu não acho que seja possível que videoWriter do OpenCV produza taxa de quadros variável (mas eu não sou especialista nisso).

Observação: seria mais fácil corrigir esse problema se o vídeo original fosse codificado com uma taxa de quadros errada constante . Você poderia então forçar o ffmpeg a assumir uma outra taxa de quadros para o vídeo de entrada, removendo efetivamente os timestamps originais e gerando novos, assumindo uma taxa de quadros constante. Por exemplo, se a sua conversão de vídeo acabou criando um vídeo de 30 fps, mas sua entrada original foi de 29 fps, faça o seguinte:

ffmpeg -r 29 -i <input> …
    
por 02.04.2017 / 21:42