ข้อผิดพลาดแปลก ๆ เมื่อใช้ ffmpeg ในวง


23

ฉันมี bash script วนซ้ำผ่านผลลัพธ์ของการค้นหาและทำการเข้ารหัส 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
ฉันพบวิธีแก้ปัญหาแล้ว สคริปต์ทุบตีดูเหมือนจะป้อนข้อมูลผลิตภัณฑ์ (คือปุ่ม 'c') ซึ่งรบกวนกระบวนการ ffmpeg ไปป์ไลน์ "</ dev / null" ให้เป็น ffmpeg เช่นนั้น: ffmpeg -i "./$f" -vcodec libx264 -vprofile high -preset high -preset ช้า -b: v 500k-maxrate 500k -bufsize 1000k -th เธรด 0 -acodec libfaac -ab 128k "./mp4s/$MP4FILENAME" </ dev / null แก้ไขปัญหา ผ่าน [ linuxquestions.org/questions/programming-9/… [1]: linuxquestions.org/questions/programming-9/…
Mark Williams

คำตอบ:


56

คำถามของคุณคือคำถามที่พบบ่อยทุบตี # 89 : เพียงเพิ่ม</dev/nullเพื่อป้องกันffmpegการอ่านอินพุตมาตรฐาน


ฉันได้ทำการแก้ไขสคริปต์ให้คุณแล้วเนื่องจากมีข้อผิดพลาดที่อาจเกิดขึ้นมากมาย ประเด็นสำคัญบางประการ:

  • ชื่อไฟล์นั้นยุ่งยากในการจัดการเพราะระบบไฟล์ส่วนใหญ่อนุญาตให้พวกเขามีอักขระที่ไม่สามารถพิมพ์ได้ทุกประเภทที่คนปกติจะเห็นว่าเป็นขยะ การตั้งสมมติฐานอย่างง่ายเช่น "ชื่อไฟล์มีเพียงอักขระ" ปกติ "จึงทำให้สคริปต์เชลล์ที่เปราะบางปรากฏขึ้นเพื่อทำงานกับชื่อไฟล์ "ปกติ" แล้วแบ่งวันที่พวกเขาทำงานเป็นชื่อไฟล์ที่น่ารังเกียจโดยเฉพาะที่ไม่เป็นไปตามสมมติฐานของสคริปต์ ในทางกลับกันการจัดการชื่อไฟล์อย่างถูกต้องอาจเป็นปัญหาที่คุณอาจพบว่ามันไม่คุ้มค่ากับความพยายามหากโอกาสที่จะพบชื่อไฟล์แปลก ๆ คาดว่าจะใกล้ศูนย์ (เช่นคุณใช้สคริปต์กับไฟล์ของคุณเองเท่านั้น คุณให้ชื่อไฟล์ "ง่ายๆ" ของคุณเอง) บางครั้งก็เป็นไปได้ที่จะหลีกเลี่ยงการตัดสินใจนี้โดยไม่แยกชื่อไฟล์เลย โชคดีที่เป็นไปได้ด้วยfind(1)'s -execตัวเลือก เพียงใส่{}อาร์กิวเมนต์ไปที่-execและคุณไม่ต้องกังวลกับการแยกวิเคราะห์findผลลัพธ์

  • การใช้sedหรือกระบวนการภายนอกอื่น ๆ เพื่อดำเนินการกับสตริงอย่างง่าย ๆ เช่นการลอกส่วนขยายและส่วนนำหน้านั้นไม่มีประสิทธิภาพ ให้ใช้การขยายพารามิเตอร์ซึ่งเป็นส่วนหนึ่งของเชลล์แทน (ไม่มีกระบวนการภายนอกหมายความว่ามันจะเร็วขึ้น) บทความที่เป็นประโยชน์บางเรื่องที่อยู่ด้านล่าง:

    • Bash FAQ 73 : การขยายพารามิเตอร์
    • Bash FAQ 100 : การจัดการสตริง
  • ใช้$( )และไม่ใช้``อีกต่อไป: 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
มันเป็นคำตอบที่ยอดเยี่ยม! ขอบคุณสำหรับความพยายามในการเขียนสคริปต์ที่ถูกต้อง แค่สงสัยว่าจะมีคล้ายกับคู่มือ Wiki ของ Greg เพื่อ zsh? ขอบคุณ!
ศิลปะ

1
@Art zshขออภัยผมไม่ทราบว่ามากเกี่ยวกับ บางทีคน zsh บนเว็บไซต์อาจจะรู้
jw013

ปัญหาคือฉันต้องตรวจสอบว่า ffmpeg สร้างข้อผิดพลาดหรือไม่ภายหลังสคริปต์ตัดสินใจว่าจะลบเวอร์ชันก่อนหน้าของไฟล์ที่แปลงแล้วหรือไม่ ฉันกำลังแปลง mkv เป็น mp4 สำหรับ Plex Media Server ฉันพูดติดอ่างกับไฟล์ mkv ขนาดใหญ่ดังนั้นฉันจึงตัดสินใจที่จะแปลง mkv ทั้งหมดเป็น mp4 ปัญหาอีกข้อหนึ่งคือฉันต้องตรวจสอบความล้มเหลวในการแปลงคำบรรยายสำหรับรูปแบบภาพที่ใช้ซึ่งในกรณีนี้ฉันใช้ proccess อื่นเพื่อแยกส่วนย่อย ดังนั้นฉันจะเรียกใช้ ffmpeg รับเอาท์พุทและไม่พบปัญหานี้ได้อย่างไร
dacabdi

15

ฉันพบวิธีแก้ปัญหาแล้ว สคริปต์ทุบตีดูเหมือนจะสร้างอินพุต (คือปุ่ม '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

แก้ไขปัญหา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.