Come modificare il framerate di un video senza ricodificare


14

Sto cercando di cambiare il framerate di un video MP4 (è un video GoPro a 120 fps, voglio riprodurlo a 30 fps per un effetto slow motion).

Sto usando avconv per questo:

avconv -i SourceMovie.mp4 -vf setpts=4.0*PTS -r 30 DestMovie.mp4

Funziona tecnicamente, ma ricodifica il film. Oltre ad essere lento, è ovviamente un problema di qualità. Tecnicamente dovrebbe esserci un modo per impostare gli fps nell'intestazione del video, come posso cambiarlo? (Funzionerebbe anche qualsiasi altro strumento diverso da avconv.)

Risposte:


15

MP4Box può farlo.

Il comando

MP4Box -add SourceMovie.mp4#video -raw 1 -new test

crea i file teste test_track1.h264. Ora puoi creare un file mp4 con qualsiasi framerate supportato che desideri (30 in questo esempio):

MP4Box -add test_track1.h264:fps=30 -new DestMovie.mp4

MP4Box fa parte del gpacpacchetto, quindi assicurati che sia installato.


6
Non è proprio semplice, ma l'ho capito, devi farlo in due passaggi. Estrarre prima lo stream video separatamente come raw ( MP4Box -add source.mp4#video -raw 1 -new test), quindi salvarlo nuovamente come MP4 ( MP4Box -add test_track1.h264:fps=30 -new dest.mp4). Puoi aggiungere una traccia audio anche lì (tramite #audio).
EboMike,

È meglio usare l' -singleopzione per il primo comando. MP4Box -single 1 -raw 1 SourceMovie.mp4crea solo un file SourceMovie_track1.h264anziché due.
diversenok

6

La modifica del framerate nell'intestazione del video (contenitore) non ha alcun effetto sulla stessa videostream (o audiostream). La ricodifica è l'unica opzione.

I videostream hanno timestamp e nella maggior parte dei video i frame sono interdipendenti tra loro a causa della compressione interframe. Alcuni giocatori possono accelerare e rallentare il video ma non tramite comandi incorporati o altro. Nessun giocatore può cambiare il framerate al volo quando un comando contenitore richiede di farlo. Il videofile finirà fuori specifica (cioè non seguendo gli standard) e il 99,9% dei giocatori rifiuterà di rispettarlo. È abbastanza impossibile fare quello che vuoi senza ricodificare. Ovviamente puoi aspettare con la ricodifica fino all'ultimo passaggio della modifica.


1
Grazie Thom! Stupida domanda però: perché? Ogni fotogramma ha un timestamp che obbliga il lettore a imporre una certa velocità di riproduzione? Voglio esattamente gli stessi fotogrammi, voglio solo che vengano riprodotti a una velocità diversa.
EboMike

2
Ciao Mike, no la tua domanda non è stupida, francamente il modo in cui pensi sia abbastanza intelligente. mi piace il tuo modo di pensare. Ho aggiunto ulteriori informazioni alla mia risposta perché era troppo lungo per inserirlo nella casella dei commenti.
Thom

Grazie! È abbastanza informativo. Ora per quanto riguarda la ricodifica: qual è il modo migliore per farlo con qualcosa come avconv? Ho usato la riga di comando sopra, ma ciò ha prodotto una qualità orribile - ho potuto quasi vedere ogni macroblocco.
EboMike

1
I timestamp nei flussi video sono memorizzati nel contenitore, non nello stesso bitstream h.264 grezzo, credo. Fintanto che vuoi solo cambiare il tempismo, ma non l'ordine, di quale frame viene visualizzato quando, non dovresti aver bisogno di transcodificare, ma solo rimodellare. (E se usi xcode, con hardware più veloce useresti -preset slower o veryslow per ottenere più qualità allo SAME bitrate, invece di lanciare più bit al problema. E usare -crf 18 o qualcosa del genere, non ABR)
Peter Cordes,

1
Non riesco a capire come ottenere ffmpeg per generare un framerate diverso però. Sembra che siano necessari mkvmerge / mp4box, a meno che non si riesca a ottenere ffmpeg per produrre un flusso di bit .264 non elaborato, quindi utilizzare l'opzione fps per il demuxer h.264 (che -h documenti completi che ha, dal momento che il flusso di bit non ha tempistiche informazioni, solo per l'ordinazione.)
Peter Cordes,

3

Nel caso in cui il tuo intento principale sia riprodurlo al rallentatore e non conservare il file come MP4, puoi usare lo strumento GUI MKVmerge per rimetterlo in un contenitore Matroska che può facilmente cambiare il framerate. Il remuxing è molto meglio della ricodifica, perché modifica solo i metadati e non lo stream stesso.

Innanzitutto installa il pacchetto

sudo apt-get install mkvtoolnix-gui

Quindi si avvia la GUI di MKVmerge. Ti troverai di fronte a una finestra come questa

mkvmerge gui 1

Basta premere il pulsante Aggiungi e selezionare il file o anche semplicemente trascinare e rilasciare il file nell'area "File di input". A questo punto dovresti essere in grado di selezionare il flusso video nel tuo video. Puoi anche eliminare altri flussi, poiché comunque si metteranno in mezzo.

Dopo averlo selezionato, dovresti vedere attive le schede in basso:

inserisci qui la descrizione dell'immagine

Passa a "Formatta azioni specifiche"

inserisci qui la descrizione dell'immagine

Puoi vedere che esiste un campo "FPS", in cui puoi inserire il valore dei frame al secondo. Sembrava che avessi intenzione di rallentare quattro volte, quindi il tuo obiettivo sarebbe stato di circa 7 frame al secondo. Puoi anche usare l'opzione "Allunga per".

Dopodiché puoi semplicemente cambiare il nome del file di output (se lo desideri) e premere "Avvia muxing".

Il programma verrà eseguito e dovresti avere il tuo file.


2

Volevo anche un rallentamento senza perdita dei miei film da 120 FPS a 30 FPS. Ho realizzato uno script che lo fa cambiando il tempo del suono e modificando l'FPS direttamente nel contenitore MP4. Sono richiesti i seguenti strumenti:

  1. avconv per convertire flussi audio
  2. sondstretch per rallentare il tempo audio
  3. gpac per ottenere MP4Box per cambiare FPS

Lo script utilizzato per la conversione è qui:

#!/bin/bash
#########################################
# Lossless slow down from 120 to 30 FPS #
#                                       #
# Use:                                  #
#                                       #
#   slow.bash <mp4_file>                #
#                                       #
#                           #-= OSi =-# #
#########################################


# Prepare basic variables
IN_FILE="$1"
NAME=$(echo "${IN_FILE}" | sed 's/\.[^.]*//')


# Clean up before start
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264" "${NAME}_slow.mp4"


# Slow down sound
avconv -i "${IN_FILE}" -vn -acodec pcm_s16le "${NAME}_.wav"
soundstretch "${NAME}_.wav" "${NAME}.wav" -tempo=-75
avconv -i "${NAME}.wav" -vn -codec:a ac3_fixed -b:a 448k "${NAME}.ac3"


# Change video frame rate and multiplex with slowed sound
MP4Box -add "${IN_FILE}#video" -raw 1 -new "${NAME}"
MP4Box -add "${NAME}_track1.h264:fps=30" -add "${NAME}.ac3" -new "${NAME}_slow.mp4"


# Clean up when we are done
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264"

Questo script crea una copia di MP4 con _slow postfix.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.