pemotongan video (+ audio) yang akurat dengan ffmpeg

10

Saya ingin situs web saya memungkinkan pengguna untuk secara akurat membuat klip mereka sendiri dari video sumber yang saya berikan.

Saya memiliki file video sumber yang ingin saya konversikan menjadi sesuatu yang cocok untuk situs web:

Input #0, matroska,webm, from 'source.mkv': 
Duration: 00:28:18.57, start: 0.000000, bitrate: 10183 kb/s 
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 48 tbc (default)
Stream #0:1: Audio: mp3, 44100 Hz, stereo, s16, 128 kb/s (default)

Saya menggunakan ffmpeg untuk mengubahnya seperti:

ffmpeg -i source.mkv -c:v libx264 -c:a aac -strict experimental -vf scale="960:-1" source.mp4

Menonton video ini kembali itu kualitas yang cukup baik dan ukuran file yang cukup kecil untuk kebutuhan saya, dan memuat / memutar di situs web saya.

Saya memiliki halaman web yang memungkinkan pengguna memilih awal dan titik akhir pada video ini - dan membuat klip. Berikut adalah contoh dari perintah ffmpeg yang saya gunakan untuk itu:

-ss 577.920 -i source.mp4 -t 011.980 -codec:v copy -codec:a copy -vf scale="960:-1" clip1.mp4

Masalahnya adalah klip tidak selalu cukup akurat waktu. Biasanya audionya cukup akurat tetapi videonya berhenti setengah detik lebih awal atau lebih.

Apakah ada cara untuk membuat ini akurat dan tidak sinkron untuk mengatakan, 0,2 detik?

EDIT: Menambahkan -force_key_frames 00:00:00.2tidak membantu.

EDIT: Saya mengubah kliping untuk digunakan -c:v libx264 -c:a aac -strict experimentalbukan -codec:v copy -codec:a copydengan hasil (ish) yang baik.

File dapat diputar secara eksternal tanpa masalah - tetapi ketika saya memuatnya ke elemen video html5 saya dan memutarnya - bagian terakhir video (audio baik-baik saja) membeku. Bagian terakhir yang membeku kurang dari sedetik.

Haruskah saya mencobanya dengan encoder video lain? Apa alternatif terbaik untuk libx264? Mengingat saya mungkin ingin ini ada di situs web publik.

Tapi tunggu dulu, bukankah fakta bahwa itu diputar secara akurat tanpa masalah dengan pemain seperti MPC atau Windows Media Player menunjukkan bahwa itu masalah dengan Google Chrome atau elemen video HTML? Atau apakah saya menggunakan penyandian yang tidak didukung atau sesuatu?

Pete Oakey
sumber
Ini mungkin ada hubungannya dengan waktu bingkai kunci. Bagaimanapun, ini harus dipindahkan ke SuperUser.com.
Brad
Hai, ffmpeg tidak dapat memotong video di titik mana pun, hanya dapat memotong frame kunci; untuk alasan ini audio hampir tepat, sedangkan video tidak.
Bisakah saya memindahkannya sendiri? Saya akan mencoba menambahkan bingkai kunci ke file sumber dengan -force_key_frames 00:00: 00.2
Pete Oakey

Jawaban:

9

Perilaku -ssperubahan tergantung jika digunakan sebagai opsi input atau output, dan seringkali lebih lambat tetapi bisa lebih akurat bila digunakan sebagai opsi output. Lihat jawaban untuk ffmpeg mengkonversi video dari periode waktu yang ditentukan secara perlahan untuk detail dan contoh lebih lanjut.

Untuk mengubah kualitas output untuk source.mp4menggunakan -crfopsi dengan nilai antara 18-28 (23 adalah default). Lihat bagian CRF dari Panduan Pengkodean FFmpeg dan x264 untuk contohnya.

Perintah pemangkasan Anda dapat disederhanakan:

ffmpeg -ss 577.92 -i source.mp4 -ss 0 -t 11.98 -c copy -map 0 clip1.mp4

Saya diganti -codec:v copy -codec:a copydengan -c copy -map 0. Ini akan menyalin semua aliran bukan hanya aliran video dan audio pertama - meskipun input hanya memiliki dua aliran karena perintah Anda sebelumnya. Karena Anda tidak dapat skala tanpa pengkodean ulang, oleh karena itu menjadi saling eksklusif -codec:v copy, dan karena input Anda sudah diskalakan ke ukuran yang ditetapkan saya menghapus opsi filter.

Jika masih kurang akurat maka cobalah:

ffmpeg -i source.mp4 -ss 577.92 -t 11.98 -c copy -map 0 clip1.mp4

Ini akan lebih lambat, tetapi mungkin lebih akurat. Lihat tautan dalam jawaban di tautan pertama yang saya berikan untuk deskripsi perbedaan kedua contoh ini.

Terakhir, Anda harus menjalankan source.mp4melalui qt-faststart(terletak di direktori alat-alat dalam sumber ffmpeg), atau menggunakan -movflags faststartpilihan. Ini akan memindahkan beberapa data ke awal file sehingga dapat memulai pemutaran sebelum sepenuhnya diunduh.

llogan
sumber
+1 untuk kiat-kiatnya tetapi saya mencoba ffmpeg -i source.mp4 -ss 577.92 -t 011.980 -c copy -map 0 clip1.mp4 tetapi bagian pertama (hampir satu detik) dan bagian terakhir (mungkin seperempat detik) dari video terjawab, audio baik-baik saja.
Pete Oakey
@PeteOakey Sudahkah Anda mencoba memotong tanpa menyalin bitstream, tetapi sebenarnya menyandikan ulang?
slhck
Mencoba tanpa salinan bitstream - hasil ditambahkan ke pertanyaan saya.
Pete Oakey
3
Menggunakan -sssebagai opsi output daripada opsi input memperbaiki masalah saya: frame video pertama sekitar 1s di video output, dengan hanya audio sebelumnya (juga dikonfirmasi oleh ffprobe -show_frames). Bergerak -sssetelah -imembuatnya menghasilkan frame audio dan video mulai dari frame 0.
CodeManX