Дивні помилки під час використання ffmpeg у циклі


23

У мене є скрипт bash, який проглядає результати пошуку та виконує кодування ffmpeg деяких файлів FLV. У той час як сценарій працює, вихід ffmpeg здається перерваним і видає деякі дивні помилки, схожі на наведені нижче. Я поняття не маю, що тут відбувається. Чи може хтось вказати мені в правильному напрямку?

Це як би цикл все ще працює, коли його не повинно бути і перериває процес ffmpeg.

Конкретна помилка:

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'

Ще кілька деталей із результату 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'

Сценарій такий

#!/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

Я не дуже сценарій, але очевидна пропозиція - попросіть ваш сценарій роздрукувати рядки, які він виконує. Вони можуть бути не такими, як ти думаєш.
Faheem Mitha

Як побічне питання: mp4filename=$(basename "$f" mp4)може бути корисним (див. man basenameТа man dirnameдля отримання додаткової інформації)
Peter.O

Скажіть, bash -x myscriptщоб отримати послідовний слід виконання сценарію, з розширенням усіх змінних. О, і до речі, ви винаходили basenameколесо на FILENAME=лінії. :)
Warren Young

1
Я знайшов рішення. Сценарій bash, здається, вводить продукт (а саме клавіша 'c'), яка перешкоджає процесу ffmpeg. Передача "</ dev / null" у ffmpeg, як-от: ffmpeg -i "./$f" -vcodec libx264 -vprofile high-predeset slow -b: v 500k -maxrate 500k -bufsize 1000k -threads 0 -acodec libfaac -ab 128k "./mp4s/$MP4FILENAME" </ dev / null Виправляє проблему. через [ linuxquestions.org/questions/programming-9/… [1]: linuxquestions.org/questions/programming-9/…
Марк Вільямс

Відповіді:


56

Ваше запитання - насправді Bash FAQ # 89 : просто додайте, </dev/nullщоб не ffmpegчитати його стандартний вклад.


Я вирішив налаштувати ваш сценарій для вас, оскільки він містить багато можливих помилок. Кілька важливих моментів:

  • Імена файлів важко обробляти, тому що більшість файлових систем дозволяють їм містити всілякі символи, що не можна друкувати, звичайні люди бачать як сміття. Спрощення припущень типу "назви файлів містять лише" звичайні "символи", як правило, призводить до появи крихких скриптів оболонкипрацювати над "звичайними" іменами файлів, а потім перервати день, коли вони зіткнуться з особливо неприємним ім'ям файлу, яке не відповідає припущенням сценарію. З іншого боку, правильне поводження з іменами файлів може бути таким клопотом, що ви можете вважати, що не варто докладати зусиль, якщо очікується, що шанс зустріти дивне ім’я файлу буде майже нульовим (тобто ви використовуєте сценарій лише для своїх власних файлів і ви даєте власним файлам "прості" імена). Іноді цілком можна уникнути цього рішення, взагалі не розбираючи імена файлів. На щастя, це можливо за допомогою і вам не доведеться турбуватися про аналіз результатів.find(1)«S -execваріант. Просто поставте {}в аргумент до-execfind

  • Використання sedчи інших зовнішніх процесів для виконання простих струнних операцій, таких як зачистка розширень та префіксів, неефективна. Натомість використовуйте розширення параметрів, які є частиною оболонки (жоден зовнішній процес не означає, що це буде швидше). Нижче наведено кілька корисних статей на цю тему:

  • Використовуйте $( )та не використовуйте ``більше: Bash FAQ 82 .

  • Уникайте використання імен змінних UPPERCASE. Цей простір імен, як правило, зарезервований оболонкою для спеціальних цілей (наприклад PATH), тому використовувати його для власних змінних - погана ідея.

А тепер, без зайвих прихисток, ось вам очищений сценарій:

#!/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
' _ {} +

Примітка. Я використовував POSIX, shоскільки ви не використовували або не потребували жодних bashспецифічних функцій у своєму оригіналі.


3
Це геніальна відповідь! Дякую за зусилля, щоб написати виправлений сценарій. Просто цікаво, чи є схожий на Greg's Wiki посібник з zsh? Спасибі!
Арт

1
@Art Вибачте, я не дуже знаю про це zsh. Можливо, хтось із zsh людей на сайті знав би.
jw013

Проблема полягає в тому, що мені потрібно перевірити, чи створює ffmpeg помилку, щоб згодом скрипт вирішити, видалити чи ні попередню версію перетвореного файлу чи ні. Я перетворюю mkv в mp4 для Plex Media Server. У мене є заїкання з великими файлами mkv, тому я вирішив перетворити всі mkv в mp4. Інша проблема полягає в тому, що мені потрібно перевірити невдачу перетворення потоку субтитрів для форматів на основі зображень, і в такому випадку я використовую інший процес для вилучення абонентів. Отже, як я запускаю ffmpeg, отримую його висновок і не стикаюся з цією проблемою?
dacabdi

15

Я знайшов рішення . Сценарій bash, здається, дає введення (а саме клавішу 'c'), яка заважає ffmpegпроцесу.

Додавання < /dev/nullдо ffmpegкомандного рядка:

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

виправляє проблему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.