FFmpeg membagi video dan bergabung kembali

8

Saya mencoba menggunakan FFmpeg untuk membagi video berdasarkan beberapa start_timedan end_timeinput, dan menggantinya dengan file video lainnya. Misalnya, untuk input 10 15saya perlu mengganti EXACT detik 10 to 15dengan video lain.

BAIK. Apa yang terlintas dalam pikiran saya adalah ini:

  1. Pisahkan dulu video (dalam hal ini, 0-10, 10-15, dan 15-end)
  2. Ganti 10-15 dengan video lainnya
  3. Gabungkan semua sub-video kembali

Pertanyaan pertama: Apakah ini solusi terbaik dan tercepat? Apakah kita memiliki perintah yang lebih mudah atau alat lain untuk mengganti periode waktu tertentu dalam video dengan video lain?

Pertanyaan kedua: Dengan asumsi FFmpeg adalah solusi yang layak, ketika saya cukup menggunakan perintah ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, kode pemrosesan video saya tidak dapat membaca dan memproses file. Saya menggunakan mediainfoalat untuk membandingkan dua file dan melihat perbedaan dalam ukuran header sementara semua hal terkait video codec adalah sama. Saya perhatikan UKURAN HEADER berbeda yang tampaknya menyebabkan masalah. Apakah ada cara untuk memaksa ukuran header juga (selain dari codec) sama?

UPDATE: Ini adalah .mp4file asli yang berfungsi dengan baik di emulator.

Ariana
sumber
Pertama kita harus berurusan dengan masalah yang Anda sebutkan di pertanyaan kedua Anda. Tolong tunjukkan perintah persis yang Anda gunakan dan output penuh, baris perintah dipotong yang Anda dapatkan dari ffmpeg. Juga tunjukkan kesalahan aktual yang Anda dapatkan saat membaca file - akan lebih baik untuk mengetahui apa sebenarnya "kode pemrosesan" Anda.
slhck
Sslhck kode pemrosesan video adalah basis kode yang sangat besar. Saya tidak bisa membagikannya. Hanya karena beberapa alasan file asli dibaca tetapi bukan yang dibuat ulang. Namun saya dapat membagikan .mp4file asli jika diperlukan.
Ariana
Saya menggunakan alat mediainfo untuk membandingkan dua file dan melihat perbedaan dalam ukuran dan hal
Ariana
Memiliki yang asli akan membantu, tetapi kami tidak akan dapat memecahkan masalah mengapa tidak dapat dibaca, saya khawatir, jika itu adalah beberapa kode internal.
slhck
Sslhck saya mengunggah file. Pertanyaan saya diperbarui
Ariana

Jawaban:

9

Menggunakan trimdan concat- sumber file dengan codec yang berbeda

Untuk ini, pastikan bahwa masing-masing file Anda memiliki resolusi yang sama, dan idealnya framerate yang sama dan subsampel kroma dll. Ini akan mencegah kesalahan atau gangguan selama penggabungan.

Anda dapat melakukan semuanya sekaligus tanpa memisahkan file, menggunakan trimdan concatfilter:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

Di sini, trimdigunakan untuk menentukan bagian individual dari stream video input ( 0:v, 1:v) yang nantinya Anda ingin gabungkan. Bagian-bagian ini dinamai v0melalui v2. ( setptsFilter akan menyetel ulang stempel waktu masing-masing komponen menjadi 0, yang diperlukan untuk penyatuan). Kemudian, kami menggabungkan tiga bagian.

Jika Anda ingin memotong dari cap waktu tertentu hingga akhir, gunakan trim=start=15alih-alih menentukan rentang.

Jika file Anda memiliki audio, Anda harus memotong aliran itu secara terpisah:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

Perhatikan bahwa video dan audio akan disandikan ulang dalam kasus ini - pastikan untuk menentukan target kualitas keluaran yang sesuai (misalnya -crfuntuk x264, x265 atau libvpx-vp9). Anda dapat membaca lebih lanjut tentang ini di FFmpeg Wiki, misalnya untuk VP9 atau H.264 .

Menggunakan segmen individual

Jika Anda ingin membagi klip dan kemudian merakitnya:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

Jika file memiliki audio, gunakan pendekatan yang sama seperti di atas:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

Ini lagi akan menyandikan ulang aliran video. Ini sedikit lebih mudah tetapi sebaliknya harus setara dengan metode di atas.

Menggunakan concatdemuxer

Pada prinsipnya Anda juga dapat mencoba menyatukan bitstream tanpa meng-encode ulang, menggunakan demuxer concat. Buat file yang dipanggil concat.txtdan tambahkan entri berikut (sesuai dengan klip video yang dibuat di atas):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

Kemudian gabungkan file-file individual ini:

ffmpeg -f concat -i concat.txt -c copy output.avi

Namun ini membutuhkan klip Anda untuk memiliki codec, resolusi, framerate dll yang sama - sehingga tidak bekerja dengan semua jenis sumber heterogen.

Menggunakan concatprotokol

Jenis penggabungan tingkat file di atas dapat dicapai dengan menggunakan concatprotokol juga, dengan jenis kendala yang sama seperti di atas (codec, resolusi, dll yang sama):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

Untuk info lebih lanjut tentang penggabungan, baca halaman Wiki FFmpeg masing - masing .

slhck
sumber
Ini terlihat sangat lengkap! Terima kasih. Saya akan mencobanya!
Ariana
Idk mengapa menggunakan concatmetode melempar kesalahan:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana
Untuk "menggunakan segmen individual", saya melihat penghentian dan sedikit memotong output. Apakah ada cara untuk memperbaikinya?
Ariana
Metode 1 bekerja dengan sempurna. Satu hal: bagaimana kita menentukan "sampai akhir" tanpa menyebutkan nomor tertentu (bukan 30 detik)
Ariana
1
Maaf, membuat kesalahan. Untuk concatdemuxer, sintaksnya berbeda. Diperbaiki sekarang Untuk mencapai akhir, gunakan trim=start=15, lihat dokumentasi trim filter: ffmpeg.org/ffmpeg-filters.html#trim - seperti untuk masalah waktu, ini sangat tergantung pada bahan sumber Anda. Belum ada masalah penggabungan dengan klip yang Anda unggah.
slhck