Gabungkan satu gambar + satu file audio untuk membuat satu video menggunakan FFmpeg

184

Ini seharusnya cukup sepele, tetapi saya tidak dapat menemukan cara untuk membuatnya bekerja.

Saya ingin FFmpeg mengambil satu gambar JPEG dan file audio sebagai input dan menghasilkan file video dengan durasi yang sama dengan file audio (dengan merentangkan gambar diam untuk seluruh durasi).

Saya tidak terlalu peduli tentang apa codec video yang digunakan untuk output, tetapi sangat penting bahwa saya dapat menggunakan "copy" sebagai codec audio (yaitu menyalin aliran audio tanpa transcoding itu).

Apa baris perintah yang tepat yang akan melakukan itu?

Saya mencoba:

ffmpeg -i image8.jpg -i sound11.amr -acodec copy test.avi

dan mencoba banyak kombinasi dengan dan tanpa -s 640x360, -loop_input, -shortest, -t xxx, -r 0.1(frame rate artifisial rendah dengan harapan bahwa video akan lebih lama) dan-f image2

Entah saya mendapatkan kesalahan atau saya mendapatkan file video dengan durasi satu frame.

Saya telah mencari-cari di sekitar dan menemukan selusin solusi yang diusulkan (seharusnya untuk pertanyaan yang sama) tidak ada yang berhasil.

Adakah yang bisa menyarankan perintah yang berfungsi dan menjelaskan alasan di baliknya?

matteo
sumber
Saya baru saja mencoba baris perintah Anda dan berhasil seperti yang diharapkan. Masalah Anda mungkin terletak pada format suara. Apakah transcoding suara berfungsi?
Kapten Giraffe
Dengan "seperti yang diharapkan", maksud Anda apakah video yang dihasilkan memiliki durasi yang sama dengan input audio? Sudahkah Anda memainkannya? Bukankah panjangnya satu frame?
matteo
Format suara bukan masalah, transcoding suara berfungsi
matteo
Saya punya masalah urutan params juga dan itu menghabiskan berjam-jam! Sayang sekali masalah semacam ini tidak tercakup dalam bantuan. gregoire.org/2009/12/05/fun-with-ffmpeg
Paul Gregoire
3
ini lebih baik daripada jawaban yang dipilih, saya bereksperimen dan cepat dan ukuran file kecil ..ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.avi
Muhammad Umer

Jawaban:

146

Urutan opsi dalam baris perintah penting. Berikut ini berfungsi untuk kasus saya:

ffmpeg -loop 1 -y -i image8.jpg -i sound11.amr -shortest -acodec copy -vcodec mjpeg result.avi

Dalam kasus yang lebih umum, di mana image.jpgdan audio.wavinput Anda, Anda dapat menggunakan perintah berikut, diadaptasi dari wiki FFmpeg :

ffmpeg -loop 1 -i image.jpg -i audio.wav -c:v libx264 -tune stillimage -c:a aac -b:a 192k -pix_fmt yuv420p -shortest out.mp4

Ini akan menggunakan libx264encoder dan memberi Anda kompresi yang lebih baik daripada codec MJPEG yang digunakan di atas. Audio adalah AAC, dengan ffmpegencoder AAC bawaan.

matteo
sumber
5
Kenapa file-file tersebut jauh lebih besar dari [ukuran gambar] + [ukuran file audio]? Saya berharap kompresi video menjadi gila dengan bingkai konstan?
Alec Jacobson
2
Itu tergantung pada codec video yang Anda gunakan. Jika Anda menyalin perintah dalam contoh saya, saya menggunakan mjpeg sebagai codec, yang mengkompres setiap frame secara terpisah, sehingga tidak mengambil keuntungan dari kenyataan bahwa semua frame sama. Juga, saya berpikir bahwa bahkan codec lainnya akan mengkode ulang seluruh frame sesekali, yaitu setiap frame N-th, sehingga Anda akan mendapatkan file yang jauh lebih kecil tetapi masih jauh lebih besar dari ukuran gambar + suara. Mereka melakukannya karena (a) jika tidak, decoder akan perlu membaca seluruh file dari awal bahkan jika Anda hanya ingin melompat ke frame terakhir, dan
matteo
2
Option shortest (finish encoding within shortest input) cannot be applied to input file image.jpg -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
wim
2
gunakan ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.aviini bekerja lebih baik !!!?! ??!?!
Muhammad Umer
2
Jawaban ini saat ini sedang dibahas dalam meta.
DavidPostill
41

Kau membuatnya cara lebih sulit daripada itu harus. FFmpeg jauh lebih pintar daripada Anda memberikannya - ia tahu Anda ingin video memiliki panjang yang sama dengan trek audio Anda.

ffmpeg -i still.png -i narrate.wav -acodec libvo_aacenc -vcodec libx264 final.flv

pause

Satu-satunya atribut Anda harus menentukan adalah input filenames, yang output codecs, dan output filename(yang eo ipso meliputi output container,).

Tentu saja, masuk akal untuk memulai dengan gambar diam yang berbagi dimensi yang sama dengan video akhirnya Anda; jika Anda menggunakan editor gambar khusus alih-alih menentukan dimensi output untuk FFmpeg untuk dipenuhi, Anda perlu memastikan dimensi input Anda adalah angka genap .

Ukuran output adalah salah satu hang-up FFmpeg yang paling umum; beberapa codec lebih terbatas dalam dimensi output daripada yang lain, tetapi tidak ada output yang dapat memiliki atribut ganjil-tinggi atau lebar.

The pauseperintah pada akhir file batch terus terbuka CLI - yang cara terbaik untuk debug baris perintah Anda adalah dengan membaca pesan kesalahan yang dihasilkannya. Mereka sangat spesifik - dan dokumentasi terbaik yang dimiliki FFmpeg - tetapi kerja keras pengembang terbuang sia-sia jika Anda membiarkan jendela ditutup sebelum Anda dapat membacanya.

Shell perintah memiliki saklar cmd /kyang mempertahankan jendela terbuka di mana Anda dapat menjalankan instruksi yang sama dari skrip batch Anda pada prompt perintah.

FFmpeg dan avconv akan membuat Anda menggunakan -c:auntuk -acodecdan -c:vuntuk -vcodecakhirnya, tetapi instruksi lama berfungsi dengan baik di build yang saya gunakan.

Nota Bene: Setiap komit memiliki kekhasan. Jika baris perintah Anda gagal tanpa alasan yang jelas, sering kali membantu untuk mencoba build lain - atau ikuti fork ke libav , tempat pengembang paling aktif FFmpeg selama beberapa tahun terakhir. Alat transcoding mereka telah diganti nama avconv tetapi file batch Anda harus bekerja dengan salah satunya.


sumber
Saya harus menggunakan versi yang berbeda dari Anda (jika Anda telah mencoba perintah Anda dan berfungsi seperti yang Anda jelaskan), karena, seperti yang sudah saya sebutkan dalam pertanyaan, saya sudah mencoba perintah yang sama persis dan saya mendapatkan video durasi dari 1 bingkai (sepersekian detik), BUKAN durasi file audio. Saya memang mengharapkannya menjadi cerdas, tetapi (dalam versi saya) ternyata tidak.
matteo
2
Hai Matteo , ya, saya memang menjalankan kode itu, dan ya, itu berfungsi seperti yang diiklankan. Saya yakin ada banyak halfwits yang akan begitu ceroboh untuk membuat klaim seperti itu tanpa mengujinya, jadi saya akan mencoba untuk tidak tersinggung :) Dalam posting lengkap di bawah ini saya akan menyediakan tautan Pastebin ke output konsol FFmpeg dan MediaInfo data pada file input dan file hasil akhir. File input saya, file batch saya, file output saya ada di GoogleDrive di mana mereka dapat didownload secara bebas , jika Anda ingin mengujinya terhadap build FFmpeg Anda.
@ShinMuraoka Mine is a win-64 ffmpeg build compiled on: Jan 6 2013, at: 16:16:53Baik solusi Anda maupun solusi @matteo bekerja untuk saya. Juga, saya mengunduh file Anda dari Google Drive, tetapi tidak memberikan output yang diharapkan (file output hitam hanya berisi audio). Tolong bantu saya dalam mencari tahu perintah yang tepat untuk digunakan.
coding_idiot
2
"tidak ada output yang dapat memiliki atribut ganjil tinggi atau lebar angka ganjil" Tidak benar. Atur pix_fmt ke sesuatu yang tidak memiliki subsampel kroma, seperti rgb24 atau yuv444p, lalu pastikan codec dan wadah mendukungnya dan tidak memiliki batasan lebih lanjut. Sehubungan dengan pix_fmt, FFmpeg kurang dari cerdas; ia mengasumsikan yuv420p (yang memiliki subsampling kroma) kecuali Anda memberi tahu sebaliknya.
Jonathan Baldwin
bagaimana dengan banyak gambar? Saya perlu gambar untuk berubah pada waktu tertentu ke gambar lain. Saya ingin dapat menentukannya di baris perintah dengan parameter waktu untuk masing-masing.
36

Lebih mudah lagi:

ffmpeg -i ep1.png -i ep1.wav ep1.flv

FFmpeg akan mencoba untuk mengambil codec terbaik secara otomatis, tergantung pada ekstensi file output Anda.

Pembaruan: Saya perhatikan YouTube mengalami kesulitan memproses video (macet pada 95%) Saya pikir karena hanya ada satu bingkai. Solusi yang saya temukan untuk membuat YouTube bahagia: tambahkan lebih banyak bingkai. Saya juga menambahkan -acodec copyuntuk menjaga kualitas audio. Anda perlu -shortestatau itu loop selamanya. (Ini berhenti di ujung aliran terpendek, yaitu audio, karena loop gambar tidak terbatas.) Urutan opsi Anda sangat penting untuk kecepatan, karena filter (dan semacamnya) diproses dalam urutan yang Anda tentukan. Jika Anda mengubah urutan parameter ini, hasilnya sangat berbeda.

ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:720 ep1.flv

Perhatikan juga bahwa saya mengatur frame rate dua kali, itu bukan kecelakaan - frame rate pertama adalah untuk input, kedua untuk output. Jika Anda melakukan ini dengan benar, seharusnya hanya ada satu frame per detik dari video, yang berarti itu mengkodekan relatif cepat. Saya juga mengatur resolusi ke 720p di sini, yang berarti Anda harus mendapatkan audio HD di YouTube :-)

PJ Brunet
sumber
Mungkin juga file audio Anda tidak akan kompatibel dengan wadah .flv Anda. Dalam hal ini, Anda harus mencoba wadah (keluaran) yang berbeda, seperti .webm, .avi atau format apa pun, hingga Anda menemukan format wadah yang kompatibel dengan file audio Anda.
PJ Brunet
1
Menggunakan ini untuk .JPG dan .MP3 untuk membuat MP4 - bekerja dengan sempurna. FLV yang saya buat dari JPG / MP3 tampaknya tidak berfungsi - yang mungkin sesuai dengan komentar komentar sebelumnya.
2
Versi yang diperbarui berfungsi, untuk Youtube. Saya pikir itu macet pada 95% tetapi akhirnya berhasil.
Basj
dapatkan ini: No pixel format specified, yuvj420p for H.264 encoding chosen. Use -pix_fmt yuv420p for compatibility with outdated media players. [libx264 @ 0x2b5c940] height not divisible by 2 (700x457)... ini berfungsi:ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:-2 video.mp4
NineCattoRules
bagaimana dengan banyak gambar? Saya perlu gambar untuk berubah pada waktu tertentu ke gambar lain. Saya ingin dapat menentukannya di baris perintah dengan parameter waktu untuk masing-masing.
14

Versi yang berfungsi untuk saya:

 ffmpeg -loop 1 -y -i pic.jpg -i sound.amr -shortest video.mp4

Checkout opsi -shortestharus di depan file output jika saya tidak mendapatkan kesalahan di bawah ini:

Opsi terpendek (menyelesaikan pengkodean dalam input terpendek) tidak dapat diterapkan ke file input pic.jpg - Anda mencoba menerapkan opsi input ke file output atau sebaliknya. Pindahkan opsi ini sebelum file miliknya. Galat opsi penguraian untuk file input pic.jpg.

fguillen
sumber
Terima kasih untuk ini. Sebagian besar jawaban lain tidak bekerja untuk saya (menggunakan ffmpeg di Alpine linux). Jawaban ini memiliki perintah terpendek yang bekerja dengan sempurna untuk saya.
DannyB
8

Dari halaman ffmpeg:

ffmpeg [[infile options][-i infile]]... {[outfile options] outfile}...

Ketika Anda menemukan, opsi infile harus datang sebelum infile yang mereka terapkan.

Namun, ini bukan bug, hanya sebuah mekanisme yang dengannya Anda dapat menentukan argumen infile mana yang berlaku.

ComputerDruid
sumber
bagaimana dengan banyak gambar? Saya perlu gambar untuk berubah pada waktu tertentu ke gambar lain. Saya ingin dapat menentukannya di baris perintah dengan parameter waktu untuk masing-masing.
4

Ini berhasil untuk saya

ffmpeg -loop 1 -shortest -y -i image.jpg -i audio.mp3 -acodec copy -vcodec libx264 video.avi

Saya menemukan vcodec libx264menciptakan file yang jauh lebih kecil daripada mpjeg(10 MB daripada 100 MB).

Kolonel Panic
sumber
1
-shortestadalah opsi keluaran dan dapat diabaikan sebagai opsi input saat Anda menggunakannya.
Logan
1

Saya mencoba melakukan sebagai @matteo , tetapi tanpa audio, dan solusi @Colonel Panic bekerja paling baik:

ffmpeg -loop 1 -shortest -y -i still.png -vcodec libx264 -t 10 video.avi

Saya hanya perlu menambahkan argumen durasi dalam detik ( -t 10).


sumber
-shortestadalah opsi keluaran, tetapi Anda menggunakannya sebagai opsi input. Pindahkan sebelum file output dan Anda dapat menghilangkannya -t 10, tetapi kemudian jawaban Anda akan hampir sama dengan yang lain.
Logan
0

ffmpeg -loop 1 -i img.jpg -i audio.wav -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest out.mp4


sumber
5
Bisakah Anda menjelaskan cara kerja perintah yang Anda tambahkan?
neelsg
Jawaban ini tidak jauh berbeda dari "komentar-jawaban" sederhana lainnya di sini.
Logan
0

Jika seseorang ingin mengonversi secara berkelompok, coba ini.

Anda dapat mengatur folder input dan output, dan juga format di mana Anda ingin video berada. Dalam hal ini saya mengaturnya ke AVI.

Jawaban ini Gabungkan satu gambar + satu file audio untuk membuat satu video menggunakan FFmpeg sangat membantu saya.

 @echo off
 set "sourcedir=C:\Users\CodeHard\Desktop\BOX\Newfolder"  
 set "outputdir=C:\Users\CodeHard\Desktop\BOX\Converted" 

 PUSHD "%sourcedir%"

 for %%F in (*.mp3) DO ffmpeg -r 1 -loop 1 -i abc.jpeg -i "%%F" -acodec copy -r 1 -shortest -vf scale=1280:720 "%outputdir%\%%F.avi"  

 POPD
Suraj Jain
sumber
-1

Coba perintah ini. Ini bekerja untuk saya.

-y -i /storage/emulated/0/images.jpg -i /storage/emulated/0/audio.wav -acodec aac -vcodec mpeg4 -s 480*320 -f mp4 -r 2 /storage/emulated/0/output.mp4"
Phani varma
sumber
2
Ini adalah perintah yang tidak lengkap yang tidak mungkin bekerja. Meskipun saya dapat memperbaiki dan men-debug perintah Anda, saya tidak akan melakukan pekerjaan Anda untuk Anda, jadi harap edit jawaban Anda dan perbaiki sendiri. Saya juga memperhatikan bahwa ukuran video Anda bukan yang diinginkan matteo.
karel