Ubah framerate dalam ffmpeg tanpa reencoding

14

Saya punya video mkv (h264) yaitu 23.976 fps (24000/1001) tapi saya ingin mengonversinya menjadi 25fps tanpa memasukkan ulang dan kehilangan kualitas. Saya tahu mkvmerge dapat melakukannya (dengan opsi --default-durasi '0: 25fps') tetapi saya ingin melakukannya secara langsung dari ffmpeg jika memungkinkan. Menurut dokumen, ini seharusnya berfungsi:

ffmpeg -i input.mkv -r 25 -vcodec copy output.mkv

tetapi ketika saya menjalankannya saya hanya mendapatkan fps video yang sama. Apa metode yang benar untuk melakukannya (jika ada) di ffmpeg?

phate89
sumber
1
Saya percaya itu tidak mungkin dengan FFmpeg saat ini. -rtidak kompatibel dengan salinan aliran, dan tidak ada filter bitstream untuk mengubah framerate.
Ely
1
sangat buruk. Saya harus menggunakan mkvmerge setiap saat. terima kasih
phate89
1
Ada cara berbelit-belit untuk melakukan ini dengan ffmpeg reguler dan cara langsung untuk melakukan ini dengan ffmpeg versi modded lama. Jika Anda tertarik, saya akan menuliskannya sebagai jawaban.
Gyan
1
Ya terima kasih .. Saya ingin melakukannya tanpa alat tambahan (saya sudah butuh ffmpeg)
phate89
1
@Mulvya Anda sedang membicarakan ini, kan? Saya ragu-ragu untuk menghubungkannya, tapi ini sudah tua sekarang. Tertarik dengan cara berbelit-belit untuk melakukannya dengan FFmpeg biasa sekalipun.
Ely

Jawaban:

15

Inilah metode menggunakan versi FFmpeg saat ini. Itu bergantung pada demuxer konat tidak men-rescaling PTS input setelah file pertama, tetapi hanya menerapkan offset tetap. Katakanlah Anda memiliki aliran 30 fps dengan skala waktu 15360(khas dari output FFmpeg). Itu berarti frame 0memiliki PTS 0dan frame 30memiliki PTS 15360. Ini akan menjadi aliran 45 fps jika kita dapat mengubah skala waktu 23040tanpa mempengaruhi nilai PTS.

Pada dasarnya, itulah yang dilakukan metode di bawah ini.

1 . Identifikasi properti sumber.

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s,
       30 fps, 30 tbr, 15360 tbn (default)

Anda ingin mencatat properti sumber, terutama resolusi dan tbn.


2a . (Opsional) Ubah skala waktu menjadi sesuatu yang nyaman, untuk membuat perhitungan lebih sederhana.

ffmpeg -i in.mp4 -c copy -an -video_track_timescale 30 in-v30.mp4

Ini membuat kita

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s, \
       30 fps, 30 tbr, 30 tbn (default

Jika Anda melakukan langkah ini, skala waktu baru harus sama atau kelipatan integral dari framerate asli.

2b . Hitung skala waktu yang dibutuhkan, sehingga untuk target framerate x, PTS dari frame # xdalam sumber harus memiliki nilai yang sama dengan yang baru tbn. Jika Anda melakukan langkah 2a, ini sangat mudah dan ini hanyalah framerate baru. Jadi, untuk fps target 45, baru tbnharus 45.


3 . Buat video dummy.

ffmpeg -f lavfi -i color=s=1280x720:r=45:d=1 -profile:v main -video_track_timescale 45 0.mp4

Semua properti harus sama seperti resolusi, profil H.264, format piksel, jumlah referensi .. dll untuk hasil terbaik.


4 Concat videonya.

Pertama buat file teks

file '0.mp4'
file 'in-v30.mp4'

Kemudian, konser itu

ffmpeg -f concat -i list.txt -c copy -video_track_timescale 45 45fps.mp4

File output akan membuat video ke-2 diputar pada 45 fps.

5 . Sekarang, bersihkan preroll boneka

ffmpeg -ss 1.1 -i 45fps.mp4 -c copy -avoid_negative_ts make_zero in45.mp4

dan kamu punya

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1757 kb/s, \
       45 fps, 45 tbr, 11520 tbn (default)

Saya memang mengatakan ini berbelit-belit!

Gyan
sumber
1
sangat pintar, jawaban yang bagus.
Rowe Morehouse