Jatuhkan setiap frame genap atau ganjil menggunakan FFmpeg?

14

Apakah ada cara akurat untuk mengambil video mentah dan mengekstraknya dari video baru yang hanya berisi bingkai aneh atau bahkan bingkai (berdasarkan pilihan)?

Sebagai contoh:

Saya memiliki "blah.yuv" dengan 400 bingkai (0-399). Saya ingin membuat "blahOdd.yuv" yang berisi bingkai 1-399 (1,3,5,7 ... 399) dan "blahEven" yang berisi bingkai 0-398 (0,2,4,6 ... 398 ).

Ada ide bagaimana melakukannya hanya menggunakan FFmpeg?

Menandai
sumber

Jawaban:

11

Untuk bekerja secara akurat, pertama-tama konversikan video ke bitstream RAW YUV (jika belum) dengan:

ffmpeg -i input.mp4 -an -vcodec rawvideo -pix_fmt yuv420p rawbitstream.yuv

Langkah selanjutnya: selectFilter mengambil ekspresi , di mana nnomor bingkai.

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="mod(n-1\,2)" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="not(mod(n-1\,2))" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an even.yuv

Agar ffmpegframe tidak duplikat, Anda harus memaksa setengah dari framerate input Anda - jadi Anda menetapkan "2" sebagai input dan "1" ke output. Jangan lupa untuk mengganti WxH dengan dimensi sebenarnya dari klip Anda karena bitstream mentah tidak memiliki header yang membawa informasi ini.

Alih-alih di atas, kemungkinan lain adalah menambahkan setptsfilter untuk mengatur cap waktu baru untuk output. Tapi hati-hati karena menjatuhkan frame tidak akurat. Di sini, 25 adalah frame rate output aktual yang Anda inginkan:

ffmpeg -i input.mp4 -filter:v select="mod(n-1\,2)",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -i input.mp4 -filter:v select="not(mod(n-1\,2))",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an even.yuv

Tentu saja Anda dapat memilih format piksel lain (salah satunya ffmpeg -pix_fmts). Pastikan bahwa saat membaca file Anda tahu ukuran piksel dan format piksel:

ffmpeg -f rawvideo -s:v 1280x720 -pix_fmt yuv420p input.yuv …
slhck
sumber
Terima kasih, Untuk versi baru FFMPEG, haruslah -vf bukan -filter: v. Selain itu harus mod (n-1 \, 2) karena n count tampaknya mulai dari 1 sedangkan frame dihitung dari 0 (jika frame pertama diduplikasi 3 kali). Tetapi masih ada masalah, itu menduplikasi bingkai sementara saya ingin menyingkirkannya - misalnya klip terakhir hanya akan berisi setengah dari frame.
Markus
-vfadalah alias dari -filter:v. Saya tidak dapat mengujinya dengan andal sekarang, tetapi akan memeriksa nanti ketika saya kembali ke komputer saya. Mungkin tinterlacefilter dapat melakukan hal yang sama?
slhck
Saya sudah mencoba '-r 2 -i blah.yuv -r 1' tetapi ini menunjukkan kepada saya opsi framerate yang
Markus
Ah maaf .. Gores itu, ini tidak berfungsi (lagi?) Dan hanya untuk gambar.
slhck
1
@AnmolSinghJaggi Tidak, ini hanya menjatuhkan frame, tapi saya tidak akan yakin bahwa itu sangat deterministik (yaitu, menjatuhkan setiap frame aneh). Ini akan didasarkan pada kode waktu, yang mungkin tidak akurat.
slhck
2

Jika ffmpeg Anda dibuat dengan bendera AviSynth, maka saya yakin Anda dapat mengirimkan .avsfile.

Anda dapat memeriksa dengan menjalankan ffmpegdan mencari --enable-avisynthdi konfigurasi data. --enable-avisynth

Jika di sana Anda dapat menggunakannya suka begitu: ffmpeg -i blahEven.avs blahEven.yuv.

Di mana blahEven.avssederhananya:

ffvideosource ("blah.yuv"). SelectEven ()

Untuk bingkai aneh, gunakan SelectOdd().

Untuk penggunaan lebih lanjut, lihat dokumentasi SelectEvery .

Louis
sumber
Ini adalah alternatif yang sangat baik, tetapi seperti yang telah saya sebutkan - saya terbatas hanya menggunakan ffmpeg. Alasan untuk itu adalah itu adalah bagian dari sistem otomatis yang hanya akan membuat file .bat, tidak ada kemungkinan untuk penambahan AVS.
Tandai
@ Mark saya berpikir bahwa jika --enable-avisynthada di sana, itu berarti AviSynth dibangun ke ffmpeg, tapi saya tidak yakin tentang itu.
Louis