2015-04-30 26 views
17

Sto utilizzando la classe JavaCV FFmpegFrameRecorder per codificare i fotogrammi di anteprima della videocamera Android in un video.Impostazione dei metadati del flusso video utilizzando Ffmpeg

L'obiettivo è quello di replicare il risultato della seguente riga di comando:

ffmpeg -i input.mp4 -metadata:s:v:0 rotate="90" output.mp4 

ho modificato il metodo startUnsafe() come segue, ma incapaci di generare il risultato desiderato:

if ((video_st = avformat_new_stream(oc, video_codec)) != null) { 
     video_c = video_st.codec(); 
     video_c.codec_id(oformat.video_codec()); 
     video_c.codec_type(AVMEDIA_TYPE_VIDEO); 
     ... 
     AVDictionary avDictionary = new AVDictionary(null); 
     av_dict_set(avDictionary, "rotate", "90", 0); 
     video_st.metadata(avDictionaty); 
     ... 
} 
... 
avformat_write_header(oc, (PointerPointer) null); 

Questo continua a codificare correttamente il video, ma i metadati aggiunti non vengono mai visualizzati su ffprobe. Se aiuta, la codifica video è h264.

A proposito, ecco l'output ffprobe:

ffprobe version 2.3.3 Copyright (c) 2007-2014 the FFmpeg developers 
    built on Jan 22 2015 18:22:57 with Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn) 
    configuration: --prefix=/usr/local/Cellar/ffmpeg/2.3.3 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libvorbis --enable-libvpx --enable-libass --enable-ffplay --enable-libfdk-aac --enable-libopus --enable-libquvi --enable-libx265 
    libavutil  52. 92.100/52. 92.100 
    libavcodec  55. 69.100/55. 69.100 
    libavformat 55. 48.100/55. 48.100 
    libavdevice 55. 13.102/55. 13.102 
    libavfilter  4. 11.100/4. 11.100 
    libavresample 1. 3. 0/1. 3. 0 
    libswscale  2. 6.100/2. 6.100 
    libswresample 0. 19.100/0. 19.100 
    libpostproc 52. 3.100/52. 3.100 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'abcd.mp4': 
    Metadata: 
    major_brand  : isom 
    minor_version : 512 
    compatible_brands: isomiso2avc1mp41 
    encoder   : Lavf56.15.102 
    Duration: 00:00:19.48, start: 0.023220, bitrate: 572 kb/s 
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1/0x31637661), yuv420p, 1280x720, 573 kb/s, 5.71 fps, 30 tbr, 15360 tbn, 60 tbc (default) 
    Metadata: 
     handler_name : VideoHandler 
    Stream #0:1(und): Audio: aac (mp4a/0x6134706D), 44100 Hz, mono, fltp, 64 kb/s (default) 
    Metadata: 
     handler_name : SoundHandler 

Qualche suggerimento su perché è fallendo? Grazie.

+0

Domanda simile: http://stackoverflow.com/questions/17024192/how-to-set-header-metadata-to-encoded-video –

risposta

1

Il FFmpegFrameRecorderclass che si utilizza utilizza AVFormatContextclass. Intorno alla linea 2579 si può vedere dalle firme del metodo, che la classe AVFormatContext utilizza codice nativo per implementare sia il metodo

  • public native AVDictionary metadata() metodo
  • public native AVFormatContext metadata(AVDictionary metadata).

La risposta al link che hai fornito dice che hanno usato la proprietà metadata del AVFormatContext direttamente - qualcosa come il primo metodo che penso. Ma la linea 649 di FFmpegFrameRecorder utilizza il secondo metodo - ho il sospetto. vale a dire:

AVDictionary metadata = new AVDictionary(null); 
... code to fill up dictionary ... 
... 

avformat_write_header(oc.metadata(metadata), options); 

Purtroppo non posso provare questo in questo momento, ma mi chiedo se si poteva fare qualcosa di simile:

AVDictionary metadata = co.metadata(); 
... code to fill up dictionary ... 

//I would assume at this point that oc has the metadata so 
avformat_write_header(oc, (PointerPointer) null); 
//if not then maybe 
// avformat_write_header(oc.metadata(metadata), options); 

La firma dimostra che è pubblico, quindi non fare vedere perché non è possibile ottenere direttamente il dizionario dei metadati dallo AVFormatContext. Non sono sicuro di come funzioni il metodo , quindi ho suggerito due cose sopra.

Nota: I non ha utilizzato questa libreria in precedenza. Ho provato, senza successo, a utilizzare Xuggler in passato per alcune codifiche di base.

4

Sembra che questa domanda abbia suscitato molto interesse, quindi aggiungo ulteriori informazioni. A seguito di questo GitHub issue Samuel da JavaCV committed alcune modifiche per consentire un più facile accesso alle impostazioni dei metadati.

metadati impostazione può essere raggiunto attraverso il seguente frammento di codice:

AVDictionary metadata = new AVDictionary(null); 
for (Entry<String, String> e : videoMetadata.entrySet()) { 
    av_dict_set(metadata, e.getKey(), e.getValue(), 0); 
} 
video_st.metadata(metadata); 

È possibile attivare in questo momento facendo mvn install -Pffmpeg o attendere fino a quando la prossima release JavacV, che dovrebbe essere 0,12.

PS: Come potete vedere, questo è molto simile a quello che ho presentato nella mia domanda, quindi non sono sicuro del motivo per cui non ha funzionato in primo luogo.