Kesalahan aneh saat menggunakan ffmpeg dalam satu lingkaran

23

Saya memiliki skrip bash looping melalui hasil dari menemukan dan melakukan pengkodean ffmpeg dari beberapa file FLV. Ketika skrip berjalan, output ffmpeg tampaknya diinterupsi dan mengeluarkan beberapa kesalahan yang tampak aneh seperti di bawah ini. Saya tidak tahu apa yang sedang terjadi di sini. Adakah yang bisa mengarahkan saya ke arah yang benar?

Seolah-olah loop masih berjalan ketika seharusnya tidak dan menginterupsi proses ffmpeg.

Kesalahan spesifik adalah:

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'

Beberapa detail lebih lanjut dari keluaran 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'

Scriptnya adalah sebagai berikut

#!/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
Mark Williams
sumber
Saya tidak banyak penulis, tetapi saran yang jelas - minta skrip Anda mencetak baris yang sedang dijalankan. Mereka mungkin tidak seperti yang Anda pikirkan.
Faheem Mitha
Sebagai masalah sampingan: mp4filename=$(basename "$f" mp4)mungkin bermanfaat (lihat man basenamedan man dirnameuntuk info lebih lanjut)
Peter.O
Katakanlah bash -x myscriptuntuk mendapatkan jejak baris demi baris dari eksekusi skrip, dengan semua variabel diperluas. Oh, dan kebetulan, Anda telah menemukan kembali basenameroda di FILENAME=telepon. :)
Warren Young
1
Saya sudah menemukan solusinya. Script bash tampaknya input produk (Yaitu kunci 'c') yang mengganggu proses ffmpeg. Memipiskan "</ dev / null" ke ffmpeg seperti: ffmpeg -i "./$f" -vcodec libx264 -vprofile high -preset lambat -b: v 500k -maksrate 500k -bufsize 1000k -baca 0k -baca 0 -acodec libfaac -ab 128k "./mp4s/$MP4FILENAME" </ dev / null Memperbaiki masalah. via [ linuxquestions.org/questions/programming-9/… [1]: linuxquestions.org/questions/programming-9/…
Mark Williams

Jawaban:

56

Pertanyaan Anda sebenarnya adalah Bash FAQ # 89 : tambahkan saja </dev/nulluntuk mencegah agar tidak ffmpegmembaca input standarnya.


Saya telah mengambil kebebasan untuk memperbaiki skrip Anda karena berisi banyak kesalahan potensial. Beberapa poin penting:

  • Nama file rumit untuk ditangani, karena sebagian besar sistem file memungkinkannya memuat semua jenis karakter yang tidak patut yang tidak biasa dilihat orang sebagai sampah. Membuat asumsi yang disederhanakan seperti "nama file hanya berisi karakter 'normal'" cenderung menghasilkan skrip shell yang rapuh yang munculuntuk bekerja pada nama file "normal" dan kemudian istirahat hari mereka mengalami nama file yang sangat jahat yang tidak mengikuti asumsi skrip. Di sisi lain, penanganan nama file yang benar bisa sangat merepotkan sehingga Anda mungkin merasa tidak sepadan jika peluang menemukan nama file yang aneh diperkirakan mendekati nol (yaitu Anda hanya menggunakan skrip pada file Anda sendiri dan Anda memberi file Anda sendiri nama "sederhana"). Terkadang dimungkinkan untuk menghindari keputusan ini sama sekali dengan tidak menguraikan nama file sama sekali. Untungnya, yang mungkin dengan find(1)'s -execpilihan. Masukkan saja {}argumen ke -execdan Anda tidak perlu khawatir tentang parsing findoutput.

  • Menggunakan sedatau proses eksternal lainnya untuk melakukan operasi string sederhana seperti ekstensi stripping dan awalan tidak efisien. Sebagai gantinya, gunakan ekspansi parameter yang merupakan bagian dari shell (tidak ada proses eksternal berarti akan lebih cepat). Beberapa artikel bermanfaat tentang hal ini tercantum di bawah ini:

  • Gunakan $( ), dan jangan gunakan ``lagi: Bash FAQ 82 .

  • Hindari menggunakan nama variabel UPPERCASE. Namespace itu biasanya disediakan oleh shell untuk tujuan khusus (seperti PATH), jadi menggunakannya untuk variabel Anda sendiri adalah ide yang buruk.

Dan sekarang, tanpa basa-basi lagi, inilah skrip yang sudah dibersihkan untuk Anda:

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

Catatan: Saya menggunakan POSIX shkarena Anda tidak menggunakan atau memerlukan bashfitur-spesifik dalam dokumen asli Anda.

jw013
sumber
3
Itu jawaban yang brilian! Terima kasih atas upaya menulis naskah yang diperbaiki. Hanya ingin tahu apakah ada yang mirip dengan panduan Wiki Greg untuk zsh? Terima kasih!
Seni
1
@ Art Maaf, saya tidak tahu banyak tentang zsh. Mungkin beberapa orang zsh di situs akan tahu.
jw013
Masalahnya adalah bahwa saya perlu memeriksa apakah ffmpeg menghasilkan kesalahan untuk nanti skrip memutuskan apakah akan menghapus versi sebelumnya dari file yang dikonversi. Saya mengonversi mkv ke mp4 untuk Server Media Plex. Saya gagap dengan file mkv besar, jadi saya memutuskan untuk mengonversi semua mkv ke mp4. Masalah lain adalah bahwa saya perlu memeriksa kegagalan konversi subtitle streaming untuk format berbasis gambar, dalam hal ini saya menggunakan proses lain untuk mengekstrak subs. Jadi, bagaimana saya menjalankan ffmpeg, mendapatkan outputnya, dan tidak mengalami masalah ini?
dacabdi
15

Saya sudah menemukan solusinya . Script bash tampaknya menghasilkan input (Yaitu kunci 'c') yang mengganggu ffmpegproses.

Menambahkan < /dev/nullke ffmpegbaris perintah, seperti:

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

memperbaiki masalah.

Mark Williams
sumber