Dziwne błędy podczas używania ffmpeg w pętli


23

Mam skrypt bash zapętlający wyniki wyszukiwania i wykonujący kodowanie ffmpeg niektórych plików FLV. Podczas działania skryptu wydaje się, że dane wyjściowe ffmpeg zostały przerwane i generują dziwnie wyglądające błędy, takie jak ten poniżej. Nie mam pojęcia, co się tutaj dzieje. Czy ktoś może skierować mnie we właściwym kierunku?

To tak, jakby pętla nadal działała, kiedy nie powinna, i zakłócała ​​proces ffmpeg.

Konkretny błąd to:

frame=   68 fps= 67 q=28.0 00000000000000000000000000001000size=      22kB time=00:00:00.50 bitrate= 363.2kbits/s dup=1 drop=0    
Enter command: <target> <time> <command>[ <argument>]
Parse error, at least 3 arguments were expected, only 1 given in string 'om/pt_br/nx/R3T4N2_HD3D_demoCheckedOut.flv'

Kilka dodatkowych szczegółów z wyjścia ffmpeg:

[buffer @ 0xa30e1e0] w:800 h:600 pixfmt:yuv420p tb:1/1000000 sar:0/1 sws_param:flags=2
[libx264 @ 0xa333240] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.1 Cache64
[libx264 @ 0xa333240] profile High, level 3.1
[libx264 @ 0xa333240] 264 - core 122 r2184 5c85e0a - H.264/MPEG-4 AVC codec - Copyleft 2003-2012 - http://www.videolan.org/x264.html - options: cabac=1 ref=5 deblock=1:0:0 analyse=0x3:0x113 me=umh subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=2 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=50 rc=cbr mbtree=1 bitrate=500 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=500 vbv_bufsize=1000 nal_hrd=none ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to './mp4s/pt_br/teamcenter/tc8_interactive/videos/8_SRM_EN.mp4':
  Metadata:
    audiodelay      : 0
    canSeekToEnd    : true
    encoder         : Lavf54.3.100
    Stream #0:0: Video: h264 (![0][0][0] / 0x0021), yuv420p, 800x600, q=-1--1, 500 kb/s, 30k tbn, 29.97 tbc
    Stream #0:1: Audio: aac (@[0][0][0] / 0x0040), 44100 Hz, mono, s16, 128 kb/s
Stream mapping:
  Stream #0:1 -> #0:0 (vp6f -> libx264)
  Stream #0:0 -> #0:1 (mp3 -> libfaac)
Press [q] to stop, [?] for help
error parsing debug value0 00000000000000000000000000000000size=      13kB time=00:00:00.-3 bitrate=-3165.5kbits/s dup=1 drop=0    
debug=0
frame=   68 fps= 67 q=28.0 00000000000000000000000000001000size=      22kB time=00:00:00.50 bitrate= 363.2kbits/s dup=1 drop=0    
Enter command: <target> <time> <command>[ <argument>]
Parse error, at least 3 arguments were expected, only 1 given in string 'om/pt_br/nx/R3T4N2_HD3D_demoCheckedOut.flv'

Skrypt jest następujący

#!/bin/bash
LOGFILE=encodemp4ize.log
echo '' > $LOGFILE
STARTTIME=date
echo "Started at `$STARTTIME`" >> $LOGFILE
rsync -avz flvs/ mp4s/ --exclude '*.flv'
#find flvs/ -name "*.flv" > flv-files
# The loop
find flvs/ -name "*.flv" | while read f
do
FILENAME=`echo $f | sed 's#flvs/##'`
MP4FILENAME=`echo $FILENAME | sed 's#.flv#.mp4#'`
ffmpeg -i "$f" -vcodec libx264 -vprofile high -preset slow -b:v 500k -maxrate 500k -bufsize 1000k -threads 0 -acodec libfaac -ab 128k "./mp4s/$MP4FILENAME"
echo "$f MP4 done" >> $LOGFILE
done

Nie jestem wielkim pismem, ale oczywistą sugestią - niech twój skrypt wydrukuje wiersze, które wykonuje. Mogą nie być tym, czym myślisz, że są.
Faheem Mitha,

Jako kwestia poboczna: mp4filename=$(basename "$f" mp4)może być przydatna (patrz man basenamei man dirnamewięcej informacji)
Peter.O

Powiedzmy, bash -x myscriptaby uzyskać liniowe śledzenie wykonania skryptu z rozszerzonymi wszystkimi zmiennymi. Aha, nawiasem mówiąc, na nowo wymyśliłeś basenamekoło na FILENAME=linii. :)
Warren Young,

1
Znalazłem rozwiązanie. Wydaje się, że skrypt bash produkuje dane wejściowe (mianowicie klawisz „c”), co zakłóca proces ffmpeg. Pipingowanie „</ dev / null” do ffmpeg tak: ffmpeg -i "./$f" -vcodec libx264 -vprofile high -preset slow -b: v 500k -maxrate 500k -bufsize 1000k -threads 0 -acodec libfaac -ab 128k „./mp4s/$MP4FILENAME” </ dev / null Rozwiązuje problem. przez [ linuxquestions.org/questions/programming-9/… [1]: linuxquestions.org/questions/programming-9/…
Mark Williams

Odpowiedzi:


56

Twoje pytanie to tak naprawdę Bash FAQ # 89 : wystarczy dodać, </dev/nullaby uniemożliwić ffmpegodczytanie jego standardowego wejścia.


Pozwoliłem ci naprawić skrypt, ponieważ zawiera on wiele potencjalnych błędów. Kilka ważnych punktów:

  • Nazwy plików są trudne w obsłudze, ponieważ większość systemów plików pozwala im zawierać wszelkiego rodzaju niedrukowalne znaki, które zwykli ludzie postrzegaliby jako śmieci. Wprowadzanie uproszczeń, takich jak „nazwy plików zawierają tylko„ normalne ”znaki”, powoduje, że pojawiają się delikatne skrypty powłokiaby pracować nad „normalnymi” nazwami plików, a następnie zepsuć dzień, gdy napotkają szczególnie nieprzyjemną nazwę pliku, która nie spełnia założeń skryptu. Z drugiej strony, prawidłowe posługiwanie się nazwami plików może być tak kłopotliwe, że może nie być warte wysiłku, jeśli prawdopodobieństwo napotkania dziwnej nazwy pliku będzie bliskie zeru (tj. Używasz skryptu tylko dla własnych plików i nadajesz swoim plikom „proste” nazwy). Czasami można całkowicie uniknąć tej decyzji, nie analizując w ogóle nazw plików. Na szczęście, jest to możliwe z find(1)„s -execopcja. Po prostu wstaw {}argument -execi nie musisz się martwić analizowaniem finddanych wyjściowych.

  • Używanie sedlub innych zewnętrznych procesów do wykonywania prostych operacji na łańcuchach, takich jak usuwanie rozszerzeń i prefiksów, jest nieefektywne. Zamiast tego użyj rozszerzeń parametrów, które są częścią powłoki (brak zewnętrznego procesu oznacza, że ​​będzie szybszy). Niektóre pomocne artykuły na ten temat są wymienione poniżej:

  • Używaj $( )i nie używaj ``już: Bash FAQ 82 .

  • Unikaj używania nazw zmiennych UPPERCASE. Ta przestrzeń nazw jest ogólnie zarezerwowana przez powłokę do specjalnych celów (np. PATH), Więc używanie jej do własnych zmiennych jest złym pomysłem.

A teraz, bez zbędnych ceregieli, oto oczyszczony skrypt dla Ciebie:

#!/bin/sh

logfile=encodemp4ize.log
echo "Started at $(date)." > "$logfile"
rsync -avz --exclude '*.flv' flvs/ mp4s/

find flvs/ -type f -name '*.flv' -exec sh -c '
for flvsfile; do
    file=${flvsfile#flvs/}
    < /dev/null ffmpeg -i "$flvsfile" -vcodec libx264 -vprofile high \
        -preset slow -b:v 500k -maxrate 500k -bufsize 1000k \
        -threads 0 -acodec libfaac -ab 128k \
        "mp4s/${file%flv}"mp4
    printf %s\\n "$flvsfile MP4 done." >> "$logfile"
done
' _ {} +

Uwaga: Użyłem POSIX, shponieważ nie bashużywałeś ani nie potrzebowałeś żadnych specyficznych funkcji w swoim oryginale.


3
To świetna odpowiedź! Dziękujemy za wysiłek napisania poprawionego skryptu. Zastanawiam się, czy istnieje podobny przewodnik Grega po Wiki na temat zsh? Dzięki!
Art.

1
@ Art Niestety nie wiem za dużo zsh. Może niektórzy ludzie zsh na stronie będą wiedzieć.
jw013

Problem polega na tym, że muszę sprawdzić, czy ffmpeg generuje błąd, aby później w dół skryptu zdecydować, czy usunąć poprzednią wersję przekonwertowanego pliku. Konwertuję mkv na mp4 dla Plex Media Server. Mam jąkanie się z dużymi plikami mkv, więc postanowiłem przekonwertować wszystkie mkv na mp4. Innym problemem jest to, że muszę sprawdzić niepowodzenie konwersji strumienia napisów dla formatów opartych na obrazie, w którym to przypadku używam innego procesu do wyodrębnienia napisów. Jak więc uruchomić ffmpeg, uzyskać jego dane wyjściowe i nie napotkać tego problemu?
dacabdi

15

Znalazłem rozwiązanie . Wydaje się, że skrypt bash generuje dane wejściowe (mianowicie klawisz „c”), które zakłócają ffmpegproces.

Dodanie < /dev/nulldo ffmpegwiersza poleceń, tak:

ffmpeg -i "./$f" -vcodec libx264 -vprofile high -preset slow -b:v 500k -maxrate 500k -bufsize 1000k -threads 0 -acodec libfaac -ab 128k "./mp4s/$MP4FILENAME" < /dev/null

naprawia problem.

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.