在循環中使用 ffmpeg 時出現奇怪的錯誤
我有一個 bash 腳本循環遍歷查找結果並執行某些 FLV 文件的 ffmpeg 編碼。雖然腳本正在執行,但 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
您的問題實際上是Bash FAQ #89:只需添加
</dev/null
以防止ffmpeg
讀取其標準輸入。我冒昧地為您修復了您的腳本,因為它包含很多潛在的錯誤。幾個要點:
文件名很難處理,因為大多數文件系統允許它們包含各種普通人認為是垃圾的不可列印字元。做出諸如“文件名僅包含‘正常’字元”之類的簡化假設往往會導致出現脆弱的 shell 腳本處理“正常”文件名,然後打破他們遇到不符合腳本假設的特別討厭的文件名的日子。另一方面,正確處理文件名可能會很麻煩,如果預計遇到奇怪文件名的機會接近於零(即您只在自己的文件上使用腳本並且你給自己的文件“簡單”的名字)。有時可以通過根本不解析文件名來完全避免這個決定。幸運的是,使用
find(1)
’-exec
選項可以做到這一點。只需{}
輸入參數即可-exec
,您不必擔心解析find
輸出。使用
sed
或其他外部程序來執行簡單的字元串操作(如剝離副檔名和前綴)效率低下。相反,使用作為 shell 一部分的參數擴展(沒有外部程序意味著它會更快)。下面列出了一些關於該主題的有用文章:
- Bash FAQ 73:參數擴展
- Bash 常見問題解答 100:字元串操作
使用
$( )
,不再使用````: Bash FAQ 82。避免使用大寫的變數名。該命名空間通常由 shell 保留用於特殊目的(如
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
特定功能。