Połącz jeden obraz + jeden plik audio, aby utworzyć jeden film za pomocą FFmpeg


183

To powinno być dość trywialne, ale nie mogę znaleźć sposobu, aby uruchomić go.

Chcę, aby FFmpeg wziął jeden obraz JPEG i plik audio jako dane wejściowe i wygenerował plik wideo o tym samym czasie trwania co plik audio (poprzez rozciągnięcie obrazu nieruchomego na cały czas).

Nie dbam zbytnio o to, jaki kodek wideo jest używany do wyjścia, ale bardzo ważne jest, aby móc użyć „kopiowania” jako kodeka audio (tj. Skopiować strumień audio bez transkodowania).

Jaka byłaby odpowiednia linia poleceń?

Próbowałem:

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

i próbowałem wiele kombinacji i bez -s 640x360, -loop_input, -shortest, -t xxx, -r 0.1(sztucznie niski wskaźnik ramki w nadziei, że film byłby dłuższy) i-f image2

Albo dostaję błędy, albo dostanę plik wideo o czasie trwania jednej klatki.

Przeszukałem go i znalazłem kilkanaście proponowanych rozwiązań (podobno tego samego pytania), z których żadne nie działa.

Czy ktoś może zasugerować działające polecenie i wyjaśnić uzasadnienie?


Właśnie wypróbowałem twoją linię poleceń i działała zgodnie z oczekiwaniami. Twój problem może dotyczyć formatu dźwięku. Czy transkodowanie dźwięku działa?
Kapitan Giraffe

Przez „zgodnie z oczekiwaniami” masz na myśli, że powstałe wideo ma taki sam czas trwania jak wejście audio? Grałeś w to? Czy to nie jest jedna klatka?
matteo

Format dźwięku nie jest problemem, transkodowanie dźwięku działa
matteo

Miałem też problem z zamówieniem paramsa i kosztowało mnie to wiele godzin! Szkoda, że ​​tego rodzaju problemy nie są objęte pomocą. gregoire.org/2009/12/05/fun-with-ffmpeg
Paul Gregoire

3
to jest lepsza niż wybrana odpowiedź, eksperymentowałem i jest szybki, a rozmiar pliku jest mały ..ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.avi
Muhammad Umer

Odpowiedzi:


145

Kolejność opcji w wierszu poleceń ma znaczenie. Następujące działa w moim przypadku:

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

W bardziej ogólnym przypadku, gdzie image.jpgi jakie audio.wavsą twoje dane wejściowe, możesz użyć następującej komendy, zaadaptowanej z 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

libx264Użyłoby to kodera i zapewniłoby lepszą kompresję niż kodek MJPEG użyty powyżej. Audio to AAC, z wbudowanym ffmpegkoderem AAC.


5
Dlaczego pliki są o wiele większe niż [rozmiar obrazu] + [rozmiar pliku audio]? Spodziewałbym się, że kompresja wideo zwariuje ze stałą klatką?
Alec Jacobson,

2
To zależy od używanego kodeka wideo. Jeśli kopiujesz polecenia w moich przykładach, używam mjpeg jako kodeka, który kompresuje każdą ramkę osobno, więc nie korzysta z faktu, że wszystkie ramki są równe. Sądzę też, że nawet inne kodeki co jakiś czas przekodowałyby całą ramkę, tj. Każdą N-tą ramkę, więc otrzymalibyście znacznie mniejszy plik, ale wciąż znacznie większy niż tylko rozmiar obrazu + dźwięku. Robią to, ponieważ (a) w przeciwnym razie dekoder musiałby odczytać cały plik od początku, nawet jeśli po prostu chcesz przejść do ostatniej klatki, i
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
użyj ffmpeg -y -i image.png -i audio.mp3 -c:a copy result.avitego działa lepiej !!!?! ??!?!
Muhammad Umer

2
Ta odpowiedź jest obecnie dyskutowana na temat meta.
DavidPostill

41

Robisz to sposób trudniejsze niż to musi być. FFmpeg jest o wiele mądrzejszy, niż ci się wydaje - wie, że chcesz, aby wideo miało taką samą długość jak ścieżka dźwiękowa.

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

pause

Jedynymi atrybutami Państwo mają określić to input filenames, output codecsi output filename(co eo ipso obejmuje output container,).

Oczywiście sensowne jest rozpoczęcie od nieruchomego obrazu, który ma takie same wymiary jak twój ostateczny film; jeśli używasz dedykowanego edytora obrazów zamiast określania wymiarów wyjściowych do spełnienia przez FFmpeg, musisz upewnić się, że wymiary wejściowe są liczbami parzystymi .

Rozmiar wyjściowy jest jednym z najczęstszych zawieszeń FFmpeg; niektóre kodeki są bardziej ograniczone w wymiarach wyjściowych niż inne, ale żadne dane wyjściowe nie mogą mieć atrybutów wysokości lub szerokości o nieparzystej liczbie.

pausePolecenia na końcu pliku wsadowym utrzymuje otwarty CLI - w najlepszym sposobem na debugowanie wiersza poleceń jest czytanie komunikatów o błędach generuje. Są bardzo szczegółowe - i najlepsza dokumentacja, jaką posiada FFmpeg - ale ciężka praca deweloperów jest marnowana, jeśli pozwolisz zamknąć okno, zanim będziesz mógł je odczytać.

Powłoka poleceń ma przełącznik, cmd /kktóry utrzymuje otwarte okno, w którym można uruchomić te same instrukcje ze skryptu wsadowego w wierszu polecenia.

Zarówno FFmpeg, jak i avconv sprawią, że będziesz używać -c:adla -acodeci -c:vdla -vcodec, ale stare instrukcje działają dobrze w kompilacjach, których używam.

Nota Bene: Każde zatwierdzenie ma osobliwości. Jeśli Twój wiersz poleceń zawiedzie bez wyraźnego powodu, często pomocne jest wypróbowanie innej wersji - lub skorzystaj z opcji przejścia do libav , gdzie najbardziej aktywni programiści FFmpeg byli od kilku ostatnich lat. Ich narzędzie do transkodowania zostało przemianowane na avconv, ale pliki wsadowe powinny działać z jednym z nich.


Muszę używać innej wersji niż ty (jeśli wypróbowałeś swoje polecenie i działa ono tak, jak opisano), ponieważ, jak już wspomniałem w pytaniu, wypróbowałem już twoje dokładnie to samo polecenie i otrzymuję film wideo o czasie jego trwania 1 klatki (ułamek sekundy), a NIE czas trwania pliku audio. Spodziewałem się, że będzie inteligentny, ale (w mojej wersji) tak się nie stało.
matteo,

2
Hej Matteo , tak, wykonałem ten kod i tak, działa zgodnie z reklamą. Jestem pewien, że jest mnóstwo halfwits, którzy byliby tak nieostrożni, aby wysuwać takie roszczenia bez testowania ich, więc postaram się nie obrazić :) W pełnym poście poniżej podam linki Pastebin do wyjścia konsoli FFmpeg i MediaInfo dane dotyczące plików wejściowych i końcowego pliku wyjściowego. Moje pliki wejściowe, plik wsadowy i plik wyjściowy znajdują się w GoogleDrive, gdzie można je bezpłatnie pobrać , jeśli chcesz je przetestować pod kątem kompilacji FFmpeg.

@ShinMuraoka Mine is a win-64 ffmpeg build compiled on: Jan 6 2013, at: 16:16:53Ani twoje rozwiązanie, ani rozwiązanie @matteo nie działało dla mnie. Pobrałem też twoje pliki z Dysku Google, ale nie dało to oczekiwanego wyniku (plik wyjściowy był czarny, zawierał tylko dźwięk). Pomóż mi w znalezieniu właściwego polecenia, które ma być użyte.
coding_idiot

2
„żadne wyjście nie może mieć atrybutów wysokości lub szerokości nieparzystej” Nieprawda. Ustaw pix_fmt na coś, co nie ma podpróbkowania barwy, takie jak rgb24 lub yuv444p, a następnie upewnij się, że kodek i kontener go obsługują i nie mają żadnych dalszych ograniczeń. Jeśli chodzi o pix_fmt, FFmpeg jest mniej niż inteligentny; zakłada yuv420p (który ma podpróbkowanie barwy), chyba że powiesz inaczej.
Jonathan Baldwin

co z wieloma obrazami? Potrzebuję zmienić obraz w określonym czasie na inny obraz. Chciałbym móc określić je w wierszu polecenia z parametrem czasu dla każdego z nich.

36

Jeszcze łatwiej:

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

FFmpeg spróbuje automatycznie wybrać najlepszy kodek, w zależności od rozszerzenia pliku wyjściowego.

Aktualizacja: Zauważyłem, że YouTube ma trudności z przetwarzaniem wideo (utknie na poziomie 95%) Myślę, że ponieważ jest tylko jedna klatka. Rozwiązanie, które znalazłem, by uszczęśliwić YouTube: dodaj więcej ramek. Dodałem również, -acodec copyaby zachować jakość dźwięku. Potrzebujesz -shortestalbo zapętla się na zawsze. (Zatrzymuje się na końcu najkrótszego strumienia, jakim jest dźwięk, ponieważ pętla obrazu jest nieskończona.) Kolejność opcji jest bardzo ważna dla szybkości, ponieważ filtry (i takie) są przetwarzane w określonej kolejności. Jeśli zmienisz kolejność tych parametrów, wyniki będą się znacznie różnić.

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

Zauważ też, że ustawiam dwa razy częstotliwość klatek, to nie jest przypadek - pierwsza częstotliwość jest dla danych wejściowych, druga dla danych wyjściowych. Jeśli zrobisz to poprawnie, powinna być tylko jedna klatka wideo na sekundę, co oznacza, że ​​koduje się stosunkowo szybko. Ustawiłem też tutaj rozdzielczość na 720p, co oznacza, że ​​powinieneś uzyskać dźwięk HD na YouTube :-)


Możliwe też, że plik audio nie będzie zgodny z kontenerem .flv. W takim przypadku powinieneś po prostu wypróbować inny (wyjściowy) pojemnik, taki jak .webm, .avi lub inny format, aż znajdziesz format pojemnika zgodny z plikiem audio.
PJ Brunet,

1
Użyłem tego do .JPG i .MP3 do stworzenia MP4 - działało idealnie. Plik FLV, który utworzyłem z JPG / MP3, wydaje się nie działać - co może być zgodne z ostrzeżeniem o poprzednich komentarzach.

2
Zaktualizowana wersja działa na Youtube. Myślałem, że utknął na 95%, ale w końcu zadziałało.
Basj

mam to: 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)... to działa:ffmpeg -r 1 -loop 1 -i ep1.jpg -i ep1.wav -acodec copy -r 1 -shortest -vf scale=1280:-2 video.mp4
NineCattoRules

co z wieloma obrazami? Potrzebuję zmienić obraz w określonym czasie na inny obraz. Chciałbym móc określić je w wierszu polecenia z parametrem czasu dla każdego z nich.

14

Wersja, która działała dla mnie:

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

Kasa opcja -shortestmusi znajdować się przed plikiem wyjściowym, jeśli nie, pojawia się następujący błąd:

Opcja najkrótsza (zakończenie kodowania w ramach najkrótszego wejścia) nie może być zastosowana do pliku wejściowego pic.jpg - próbujesz zastosować opcję wprowadzania do pliku wyjściowego lub odwrotnie. Przenieś tę opcję przed plik, do którego należy. Błąd podczas analizowania opcji pliku wejściowego pic.jpg.


Dzięki za to. Większość innych odpowiedzi nie działała dla mnie (używanie ffmpeg na Alpine Linux). Ta odpowiedź ma najkrótsze polecenie, które działało dla mnie bezbłędnie.
DannyB,

8

Z strony podręcznika ffmpeg:

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

Jak odkryłeś, opcje infiltracji muszą znajdować się przed infilem, którego dotyczą.

Nie jest to jednak błąd, tylko mechanizm, za pomocą którego można określić, które argumenty infile mają zastosowanie.


co z wieloma obrazami? Potrzebuję zmienić obraz w określonym czasie na inny obraz. Chciałbym móc określić je w wierszu polecenia z parametrem czasu dla każdego z nich.

4

To zadziałało dla mnie

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

Odkryłem, że vcodec libx264utworzył znacznie mniejsze pliki niż mpjeg(10 MB zamiast 100 MB).


1
-shortestjest opcją wyjściową i może być ignorowana jako opcja wejściowa podczas jej używania.
llogan

1

Próbowałem zrobić jako @matteo , ale bez dźwięku, a rozwiązanie @Colonel Panic działało najlepiej:

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

Musiałem tylko dodać argument czasu trwania w sekundach ( -t 10).


-shortestjest opcją wyjściową, ale używasz jej jako opcji wejściowej. Przenieś go przed plikiem wyjściowym i możesz go wyeliminować -t 10, ale wtedy twoja odpowiedź będzie prawie taka sama jak inne.
llogan

0

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


5
Czy możesz wyjaśnić, jak działa dodane polecenie?
neelsg

Ta odpowiedź niewiele różni się od innych prostych „komentarzy-odpowiedzi” tutaj.
llogan

0

Jeśli ktoś chce je przekonwertować, spróbuj tego.

Możesz ustawić folder wejściowy i wyjściowy, a także format, w jakim chcesz wideo. W tym przypadku ustawię go na AVI.

Ta odpowiedź Połącz jeden obraz + jeden plik audio, aby zrobić jedno wideo za pomocą FFmpeg, bardzo mi pomogła.

 @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

-1

Wypróbuj to polecenie. To działa dla mnie.

-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"

2
Jest to niepełne polecenie, które prawdopodobnie nie mogłoby działać. Chociaż mogę naprawić i debugować twoje polecenie, nie wykonam za ciebie pracy, więc edytuj swoją odpowiedź i napraw ją samodzielnie. Zauważyłem również, że rozmiar twojego filmu nie jest tym, czego chciał matteo.
karel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.