2010-07-03 2 views
12

Ho bisogno di masterizzare un codice temporale per un video e mi chiedo se questo è qualcosa che ffmpeg è in grado di fare?Può ffmpeg masterizzare nel codice temporale?

+0

Quindi presumo che tu voglia masterizzare "l'ora corrente del video" nel video stesso? O vuoi usare libav * per aggiungere del testo ad un video con il tuo codice di tempo qui? – rogerdpack

risposta

3

Risposta breve, n.

Risposta lunga, sì, ma non senza usare una libreria separata per creare i fotogrammi con il codice temporale visualizzato su di essi, con trasparenza che riempie il resto del fotogramma, quindi utilizzando FFmpeg per sovrapporre i fotogrammi sul video esistente. In cima alla mia testa non so come farlo, ma sono sicuro che se sei creativo puoi capirlo.

Modifica: Ho lavorato a questo problema perché è una domanda/progetto interessante per me. Sono arrivato un po 'oltre nella soluzione scrivendo a Perl script che genererà un file .srt con il time code incorporato in esso per ogni dato file video dal quale FFmpeg è configurato per poter leggere i metadati. Utilizza la libreria Video::FFmpeg per leggere la durata e salva un file di sottotitoli come ${video}.srt. Questo farà in modo che renderà automaticamente in Mplayer se si inserisce le seguenti linee nel vostro ~/.mplayer/config:

# select subtitle files automatically in the current directory, all files 
# matching the basename of the current playing file 
sub-fuzziness=1 

Ancora lavorando su come posizionare e sovrapporre i sottotitoli resi su un video e ri-codificare nello stesso formato . Aggiornerò questo post come so di più.

+0

Questo è un approccio interessante. Qualche vantaggio su librerie che potrebbero farlo? Se no, posso guardarmi intorno. – spinon

+0

Una cosa che dovrei aggiungere visto che ovviamente stai facendo un ottimo lavoro qui. Questo è quello che sto cercando di creare un nuovo video con i timecode presenti su di esso. Quindi non solo riprodurli in un lettore, ma creare un nuovo video in modo che possa essere riprodotto in qualsiasi giocatore. Aggiungerò una generosità alla domanda dato che ci hai dedicato così tanto sforzo. – spinon

+1

Evidentemente è ora possibile con i filtri video. Vedere https://gist.github.com/reidransom/2630650 –

-1

FFMPEG sarà in grado di svolgere gran parte del lavoro, ma non sarà tutto impacchettato. Usando FFMPEG, puoi far decodificare tutti i fotogrammi in sequenza e darti il ​​"Time stamp della presentazione" (i metadati aggiuntivi relativi al tempo potrebbero essere disponibili su alcuni formati, ma PTS è ciò che vorresti cercare per iniziare .) Quindi, sei da solo a disegnare il testo sul telaio decodificato. Io uso Qt per cose simili, usando QPainter su un QImage con i dati del frame, ma ci possono essere alcune altre API per disegnare su un'immagine che trovi più ovvia. Quindi, utilizza l'API FFMPEG per creare un video compresso contenente i frame appena estratti. Sarà un po 'più complicato se vuoi anche l'audio. Il mio lavoro non interessa veramente l'audio, quindi non mi sono preso la briga di imparare gli aspetti audio dell'API. Fondamentalmente, mentre esegui il ciclo di lettura che preleva i pacchetti dal file, alcuni di essi saranno audio. Invece di scartarli come faccio io, dovrai tenerli e scriverli nel file di output come li hai ottenuti.

Ho usato solo l'API C, piuttosto che C#, quindi non so se ci sia qualche trucco speciale di cui preoccuparsi.

2

nelle versioni più recenti, è possibile utilizzare il filtro drawtext (la "t" nei suoi esempi è, credo, il timestamp del frame) per inserire il testo. Funziona anche per srtftime sul tempo di sistema "attuale".

+0

La documentazione contiene un errore, non esiste l'opzione 't'. È [chiamato basetime'] (http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavfilter/vf_drawtext.c;h=dde3b0a3202d45b82326f1f523673d52eff6236b;hb=HEAD#l190). Ad ogni modo, non ho potuto farlo funzionare correttamente. – Lekensteyn

+0

sì, a quanto pare è stato deprecato e rimosso. Alcune altre cose che potrebbero essere utili: puoi usare qualsiasi supporto "eval" e avere "frame_num" e "localtime" disponibili per le cose strftime ... – rogerdpack

+0

Vedi [la mia risposta a questa domanda] (http: // stackoverflow .com/a/20313722/427545), ieri ho scoperto alcuni altri metodi per ottenere il tempo. Il 't' sembra essere un errore di documentazione, dovrebbe essere' basetime' (che si applica solo a 'expansion = strftime'). – Lekensteyn

21

filtro DrawText di FFmpeg funziona per me, è specificare il codice di tempo iniziale e il suo formato così:

-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\ 
timecode='00\:00\:00\:00':rate=25:text='TCR\:':fontsize=72:fontcolor='white':\ 
boxcolor=0x000000AA:box=1:x=860-text_w/2:y=960" 

è necessario specificare il formato del codice di tempo nel formato hh: mm: ss [:,,] FF. Nota che devi sfuggire ai due punti nella stringa del formato del codice di tempo, e devi specificare una frequenza del codice di tempo (qui 25fps).È inoltre possibile specificare testo aggiuntivo - qui è "TCR:"

È possibile ottenere il frame rate con ffprobe e un po 'di shell fu:

frame_rate=$(ffprobe -i "movie.mov" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/") 

così si potrebbe facilmente collegare tutto insieme in un lotto - script di elaborazione, ad esempio

for i in *.mov 
frame_rate=$(ffprobe -i "$i" -show_streams 2>&1|grep fps|sed "s/.*, \([0-9.]*\) fps,.*/\1/") 
clipname=${(basename "$i")/\.*/} 
ffmpeg -i "$i" -vcodec whatever -acodec whatever \ 
-vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\ 
timecode='00\:00\:00\:00':rate=$frame_rate:text='$clipname' TCR:':\ 
fontsize=72:fontcolor='white':boxcolor=0x000000AA:\ 
box=1:x=860-text_w/2:y=960" "${i/.mov/_tc.mov}" 
done 

che dovrebbe aggiungere nome della clip e timecode rotazione in una scatola semi-opaca al centro inferiore di un telaio 1920x1080

Modifica Da quando sono venuto al lato oscuro io ora faccio questo in un ambiente Windows PowerShell, e questo è quello che uso:

ls -R -File -filter *.M*|%{ 
ffmpeg -n -i $_.fullname -vf drawtext="fontsize=72:x=12:y=12:` 
timecode='00\:00\:00\:00':rate=25:fontcolor='white':` 
boxcolor=0x000000AA:box=1" ` 
("c:\path\to\destination\{0}" -F ($_.name -replace 'M[OPT][V4S]', 'mp4'))} 

Questo crea MP4s dato una cartella contenente .MOV, .mp4 e File .MTS (usando il comando -filter cerca i file con * .M * nel nome, che dovresti modificare se stai facendo file .AVI), ed è un po 'più minimale, usa solo libx264 con le impostazioni predefinite come codec di output e non specifica font ecc. Il timecode in questo caso è bruciato nella parte in alto a sinistra del frame.

+1

Buona idea, sfortunatamente non funziona con frazioni come '12.34 fps'. – Lekensteyn

+0

hmm Lo considero un bug che non puoi usare il timecode per visualizzare le frazioni ... – rogerdpack

+0

In effetti sembra che funzioni solo per frame_rate standard, come 25, dovessi transcodificare, e anche allora, i tempi erano sbagliato per qualche ragione per me. – ntg

12

Il filtro drawtext menzionato nella risposta @stib è la chiave per inserire l'ora. L'utilizzo dell'opzione timecode, tuttavia, non corrisponde all'ora dell'orologio a muro. Se ottieni il parametro r (timecode_rate) errato, la tua ora non corrisponderà al tuo tempo di riproduzione.

Esistono altre opzioni, ad esempio l'opzione text='%{prt}' consente di visualizzare il tempo trascorso con precisione in microsecondi. Comando:

ffmpeg -i video.mp4 -vf "drawtext=text='%{prt}'" output.mp4 

Per ottenere un orologio al posto, ho dovuto usare l'opzione deprecata strftime. Questo ha un'opzione non documentata basetime che può essere utilizzata per impostare l'ora di inizio in microsecondi. Un esempio in cui ho impostato l'orario di inizio alle 12:00 il 1 ° dicembre il 2013 (la parte $(...) è coperture espansione fatta dalla shell) e hanno solo il tempo visualizzato (vedi la strftime manual for possible formats):

ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \ 
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='%H\\:%S\\:%S'" output.mp4 

\\: viene utilizzato per sfuggire allo : che altrimenti otterrebbe il significato di un separatore di opzioni.

altro esempio: un comando per inserire la data + tempo all'interno di una scatola nera, alcuni pixel dall'angolo in alto a sinistra e "certo riempimento" (in realtà, due spazi e ritorni a capo sui bordi):

newline=$'\r' 
ffmpeg -i video.mp4 -vf "drawtext=x=8:y=8:box=1:fontcolor=white:boxcolor=black: \ 
    expansion=strftime:basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='$newline %Y-%m-%d %H\\:%M\\:%S $newline'" output.mp4 

altro esempio per ottenere i microsecondi sotto l'orologio:

newline=$'\r' 
ffmpeg -i video.mp4 -vf "drawtext=expansion=strftime: \ 
    basetime=$(date +%s -d'2013-12-01 12:00:00')000000: \ 
    text='$newline %H\\:%M\\:%S $newline':fontcolor=white:box=1:boxcolor=black, \ 
    drawtext=text='$newline %{pts} $newline': \ 
    y=2*th/3:box=1:fontcolor=white:boxcolor=black:" output.mp4 

Questo utilizza il fatto che il testo è in realtà lungo tre linee e che sia testo avere una nuova riga (ritorno del carrello, ^M) anteporre e aggiunto.(Senza questa nuova riga, lo spazio viene spogliato)

Altre note:

  • -vf e -filter:v sono uguali.
  • Non è possibile specificare più filtri, ad es. -vf drawtext=text=1 -vf drawtext=text=2 disegna solo il secondo testo. Puoi combinare i filtri con una virgola come mostrato sopra. !
+0

l'opzione "localtime" è d'aiuto? http://ffmpeg.org/pipermail/ffmpeg-user/2014-July/022355.html – rogerdpack

+0

localtime non aiuta, basa l'ora locale invece di un momento fisso. Il comando che ho provato: 'ffplay -i video.mp4 -vf drawtext = 'expansion = normal: text =% {localtime \\:% a% b% d% Y}'' – Lekensteyn

+0

questo ha funzionato newline = $ '\ r ' ffmpeg -i video.mp4 -vf "drawtext = expansion = strftime: \ basetime = $ (data +% s -d'2013-12-01 12:00:00') 000000: \ text = '$ newline% H \\:% M \\:% S $ newline ': fontcolor = white: box = 1: boxcolor = black, \ drawtext = text =' $ newline% {pts} $ newline ': \ y = 2 * th/3: box = 1: fontcolor = white: boxcolor = black: "output.mp4 – Rick2047

1

La soluzione più semplice che ho trovato per mostrare l'orologio quando il file è stato catturato, non la sua durata e farlo funzionare/sulla base di questo post, grazie/è

D:\Temp\2>ffmpeg.exe -i test.avi -vf "drawtext=fontfile=C\\:/Windows/Fonts/arial.ttf:timecode='00\:20\:10\:00':rate=25:text='TCR\:':fontsize=46:fontcolor=white:x=500:y=50: box=1: [email protected]" -f mp4 textts.mp4 

Così semplice in timecode - metti la tua ora di inizio, poi il conteggio sta andando bene! L'esempio è per Windows

+0

Funziona anche su OS X dando il percorso corretto a un font – kmundnic

1

Ecco la mia soluzione, e credo che sia quella giusta, perché evita di dover impostare manualmente la velocità e consente di formattare l'output.

ffmpeg -i test.mp4 -vf \ 
    "drawtext=fontfile=arialbd.ttf:text='%{pts\:gmtime\:0\:%H\\\:%M\\\:%S}'" test.avi 

Produce un timbro nel formato HH: MM: SS; puoi cambiarlo in qualsiasi cosa desideri, usando strftime.

Potrebbe sembrare che inserirà un timestamp con gmtime, ma non è quello che succede. In realtà alimenta l'ora corrente del video, in secondi, in gmtime, producendo una data che è 1/1/1970, e un tempo che è comunque molti secondi dopo mezzanotte. Quindi devi semplicemente scartare la parte della data e usare la porzione del tempo.

Prendere nota del contatore triplo nella funzione pts, che dovrete fare se lo inserite come ho fatto sopra. Inoltre puoi vedere che ho copiato il mio file di font per Arial Bold e l'ho inserito direttamente nella directory di lavoro per semplicità.