ループでffmpegを使用する場合の奇妙なエラー


23

検索の結果をループし、いくつかのFLVファイルのffmpegエンコードを実行するbashスクリプトがあります。スクリプトが実行されている間、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

私はあまりスクリプターではありませんが、明白な提案です-実行中の行をスクリプトに出力してもらいます。彼らはあなたが思うとは違うかもしれません。
ファヒムミタ

副次的な問題として:mp4filename=$(basename "$f" mp4)役に立つかもしれません(詳細man basenameman dirname詳細については)
Peter.O

言ってbash -x myscript、すべての変数が展開して、スクリプトの実行のライン・バイ・ライントレースを取得します。ああ、ついでに、あなたはラインbasename上の車輪を再発明しましたFILENAME=。:)
ウォーレンヤング

1
私は解決策を見つけました。bashスクリプトは、ffmpegプロセスに干渉する入力(つまり「c」キー)を生成するようです。「</ 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この問題を修正します。[経由linuxquestions.org/questions/programming-9/... [1]:linuxquestions.org/questions/programming-9/...
マーク・ウィリアムズ

回答:


56

あなたの質問は、実際にはBash FAQ#89です。標準入力を読み取れ</dev/nullないように追加するだけffmpegです。


スクリプトには多くの潜在的なエラーが含まれているため、スクリプトを修正する自由を取りました。重要なポイントのいくつか:

  • ほとんどのファイルシステムでは、通常の人がゴミとみなすあらゆる種類の印刷できない文字を含めることができるため、ファイル名は扱いにくいです。「ファイル名に「通常の」文字のみが含まれる」などの単純化された仮定を行うと、脆弱なシェルスクリプトが表示される傾向があります。「通常の」ファイル名で作業し、スクリプトの仮定に従わない、特に厄介なファイル名にぶつかる日を壊します。一方、ファイル名を正しく処理するのは面倒なので、奇妙なファイル名に遭遇する可能性がゼロに近いと予想される場合、努力する価値がないと感じるかもしれません(つまり、自分のファイルでのみスクリプトを使用し、独自のファイルに「単純な」名前を付けます)。ファイル名をまったく解析しないことで、この決定を完全に回避できる場合があります。幸いなことに、これはfind(1)-execオプションで可能です。{}引数を入力するだけで、出力の-exec解析について心配する必要はありませんfind

  • sed拡張機能やプレフィックスの削除などの単純な文字列操作を行うために、またはその他の外部プロセスを使用するのは非効率的です。代わりに、シェルの一部であるパラメーター展開を使用します(外部プロセスがないため、高速になります)。この件に関する役立つ記事を以下にリストします。

  • 使用は$( )、と使用しない``もう: Bashのよくある質問82

  • 大文字の変数名を使用しないでください。その名前空間は通常、シェルによって特別な目的(など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
' _ {} +

注:オリジナルではsh特定のbash機能を使用していないか必要ないため、POSIXを使用しました。


3
それは素晴らしい答えです!修正されたスクリプトを作成してくれてありがとう。グレッグのWikiガイドに似たzshがあるのだろうか?ありがとう!
アート

1
@アート申し訳ありませんが、私はあまり知りませんzsh。多分サイトのzshの人々の何人かは知っているでしょう。
jw013

問題は、ffmpegがエラーを生成しているかどうかを確認し、後でスクリプトを変換して、変換されたファイルの前のバージョンを消去するかどうかを決定する必要があることです。Plex Media Serverのmkvをmp4に変換しています。大きなmkvファイルで途切れるので、すべてのmkvをmp4に変換することにしました。別の問題は、画像ベースのフォーマットの字幕ストリーム変換の失敗を確認する必要があることです。この場合、別のプロセスを使用して字幕を抽出します。それでは、ffmpegを実行して出力を取得し、この問題に遭遇しないようにするにはどうすればよいですか?
-dacabdi

15

私は解決策を見つけまし。bashスクリプトは、ffmpegプロセスを妨害する入力(つまり「c」キー)を生成するようです。

次のようにコマンドラインに追加< /dev/nullffmpegます。

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

問題を修正します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.