Podsumowanie
Wydaje się, że wideo H.264 ma naprawdę wysoką częstotliwość klatek, co wymaga współczynnika skalowania zastosowanego do czasu trwania filmu, który próbuję wyodrębnić (900x niższy).
Body
Próbuję wyodrębnić klip z filmu, który mam w formacie MP4 (utworzonym za pomocą Handbrake ). Po wypróbowaniu mencodera i VLC postanowiłem dać FFmpeg szansę, ponieważ było to najmniej kłopotliwe przy kopiowaniu kodeków. To znaczy, w porównaniu do mencodera i VLC, wynikowy plik był nadal odtwarzany w QuickTime (wiem o Perianie itp., Próbuję tylko dowiedzieć się, jak to wszystko działa).
W każdym razie moje polecenie było następujące:
ffmpeg -ss 01:15:51 -t 00:05:59 -i outofsight.mp4 \
-acodec copy -vcodec copy clip.mp4
Podczas kopiowania pojawia się:
Seems stream 0 codec frame rate differs from container frame rate: 45000.00 (45000/1) -> 25.00 (25/1)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from outofsight.mp4':
Duration: 01:57:42.10, start: 0.000000, bitrate: 830 kb/s
Stream #0.0(und): Video: h264, yuv420p, 720x384, 25 tbr, 22500 tbn, 45k tbc
Stream #0.1(eng): Audio: aac, 48000 Hz, stereo, s16
Output #0, mp4, to 'out.mp4':
Stream #0.0(und): Video: libx264, yuv420p, 720x384, q=2-31, 90k tbn, 22500 tbc
Stream #0.1(eng): Audio: libfaac, 48000 Hz, stereo, s16
Stream mapping:
Stream #0.0 -> #0.0
Stream #0.1 -> #0.1
Press [q] to stop encoding
frame= 2591 fps=2349 q=-1.0 size= 8144kB time=101.60 bitrate= 656.7kbits/s
…
Zamiast klipu o czasie trwania 5:59 dostaję całą resztę filmu. Aby to przetestować, uruchomiłem komendę ffmpeg -t 00:00:01
. Dostałem dokładnie 15 minutowy klip. Więc zrobiłem trochę inżynierii czarnej skrzynki i zdecydowałem się skalować moją -t
opcję, obliczając jaką wartość wprowadzić, biorąc pod uwagę, że 1 sekunda została zinterpretowana jako 900 s. Dla mojego pożądanego klipu 359 s wyliczyłem 0,399 si moje polecenie ffmpeg stało się:
ffmpeg -ss 01:15.51 -t 00:00:00.399 -i outofsight.mp4 \
-acodec copy -vcodec copy clip.mp4
Działa to, ale nie mam pojęcia, dlaczego czas trwania jest skalowany o 900. Przy dalszym badaniu, każdy bieg ffmpeg ma linię:
Seems stream 0 codec frame rate differs from container frame rate: 45000.00 (45000/1) -> 25.00 (25/1)
45000/25 = 1800. Musi być gdzieś relacja. W jakiś sposób nieprzyzwoicie wysoka częstotliwość klatek powoduje problemy z timingiem. Jaka jest tak wysoka częstotliwość odświeżania? Najlepsze w tym wszystkim jest to, że wynikowy plik clip.mp4 ma dokładnie tę samą funkcję (ze względu na skopiowany kodek wideo), a pobieranie kolejnych klipów z tego wymaga takiego samego skalowania dla -t
opcji czasu trwania. Dlatego udostępniłem go wszystkim, którzy chcą to sprawdzić.
Dodatek
Preambuła ffmpeg w moim systemie (zbudowana przy użyciu portu ffmpeg MacPorts):
FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.
configuration: --prefix=/opt/local --disable-vhook --enable-gpl --enable-postproc --enable-swscale --enable-avfilter --enable-avfilter-lavf --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libdirac --enable-libschroedinger --enable-libfaac --enable-libfaad --enable-libxvid --enable-libx264 --mandir=/opt/local/share/man --enable-shared --enable-pthreads --cc=/usr/bin/gcc-4.2 --arch=x86_64
libavutil 49.15. 0 / 49.15. 0
libavcodec 52.20. 0 / 52.20. 0
libavformat 52.31. 0 / 52.31. 0
libavdevice 52. 1. 0 / 52. 1. 0
libavfilter 1. 4. 0 / 1. 4. 0
libswscale 1. 7. 1 / 1. 7. 1
libpostproc 51. 2. 0 / 51. 2. 0
built on Jan 4 2010 21:51:51, gcc: 4.2.1 (Apple Inc. build 5646) (dot 1)
EDYCJA
Nie jestem pewien, czy to był błąd, czy nie, ale wydaje się, że został teraz naprawiony w mojej obecnej wersji ffmpeg, przynajmniej dla tego filmu (wersja 0.6.1 z MacPorts).
Odpowiedzi:
W przypadku ffmpeg pozycjonowanie opcji ma znaczenie. W twoim przykładzie próbuje zastosować -ss i -t do danych wejściowych. Użyj tego w ten sposób, zamiast tego zastosujesz opcje do danych wyjściowych:
Przy obecnej ffmpeg poprawna składnia to:
źródło
Miałem ten sam problem, a moje rozwiązanie było następujące:
exec ('ffmpeg -y -i /testmedia/'.$info['filename']. '-vf fps = fps = 1 /'.$ fracduration.' -f image2 /testmedia/images/output%03d.jpg 2 > & 1 ', $ ffmpegout); // print_r ($ ffmpegout);
To daje mi 10 zdjęć dla całego filmu, bez względu na jego długość
źródło