루프에서 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

나는 많은 스크립터는 아니지만 명백한 제안-스크립트가 실행중인 줄을 인쇄하도록하십시오. 그들은 당신이 생각하는 것과 다를 수 있습니다.
— Faheem Mitha

측면의 문제로 : mp4filename=$(basename "$f" mp4)유용 (볼 수 있습니다 man basename및 man dirname추가 정보를 원하시면)
— Peter.O

말 bash -x myscript모든 변수 확장과 함께, 스크립트의 실행을 위해 라인 추적을 얻을 수 있습니다. 아, 그리고 우연히, 당신은 선에 basename바퀴를 재발견했습니다 FILENAME=. :)
— Warren Young

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/…
— Mark Williams

답변:


56

귀하의 질문은 실제로 Bash FAQ # 89입니다 : 표준 입력을 읽지 </dev/null못하게하기 위해 추가하십시오 ffmpeg.


스크립트에 많은 잠재적 오류가 포함되어 있기 때문에 스크립트를 자유롭게 고칠 수 있습니다. 중요한 몇 가지 사항 :

  • 대부분의 파일 시스템은 보통 사람들이 볼 수있는 모든 종류의 인쇄 할 수없는 문자를 가비지로 포함 할 수 있기 때문에 파일 이름을 다루기가 까다 롭습니다. "파일 이름에 '일반적인'문자 만 포함됨"과 같은 간단한 가정을하면 깨지기 쉬운 쉘 스크립트가 나타납니다."일반적인"파일 이름으로 작업 한 다음 스크립트의 가정을 따르지 않는 특히 불쾌한 파일 이름을 사용하는 날을 깰 수 있습니다. 반면, 파일 이름을 올바르게 처리하면 이상한 파일 이름이 발생할 가능성이 거의 없을 것으로 예상되는 경우 노력할 가치가 없다는 것을 알 수 있습니다 (예 : 자신의 파일에서만 스크립트를 사용하고 자신의 파일에 "간단한"이름을 지정하십시오). 때때로 파일 이름을 파싱하지 않음으로써이 결정을 완전히 피할 수 있습니다. 다행히도 find(1)의 -exec옵션으로 가능합니다 . 그냥 넣어 {}의 인수에 -exec당신은 구문 분석에 대해 걱정하지 않아도 find출력을.

  • sed확장 및 접두사 제거와 같은 간단한 문자열 작업을 수행하기 위해 또는 다른 외부 프로세스를 사용하는 것은 비효율적입니다. 대신, 쉘의 일부인 매개 변수 확장을 사용하십시오 (외부 프로세스가 없으면 더 빠를 것입니다). 해당 주제에 대한 유용한 기사는 다음과 같습니다.

  • 를 사용 $( )하고 ``더 이상 사용하지 마십시오 : Bash FAQ 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사용하지 않았거나 필요하지 않기 때문에 POSIX를 사용했습니다 bash.


3
훌륭한 답변입니다! 수정 된 스크립트를 작성해 주셔서 감사합니다. zsh에 대한 Greg의 Wiki 안내서와 비슷한 것이 궁금하십니까? 감사!
— Art

1
@Art 죄송합니다 zsh. 에 대해 잘 모릅니다 . 어쩌면 사이트의 일부 zsh 사람들이 알고있을 것입니다.
— jw013

문제는 나중에 ffmpeg가 오류를 생성하여 스크립트를 다운 다운하여 변환 된 파일의 이전 버전을 지 울지 여부를 결정해야한다는 것입니다. Plex Media Server의 경우 mkv를 mp4로 변환하고 있습니다. 큰 mkv 파일로 말더듬을 만들었으므로 모든 mkv를 mp4로 변환하기로 결정했습니다. 또 다른 문제는 그림 기반 형식에 대한 자막 스트림 변환 실패를 확인해야한다는 것입니다.이 경우 다른 절차를 사용하여 자막을 추출합니다. 그렇다면 어떻게 ffmpeg를 실행하고 출력을 얻으며이 문제가 발생하지 않습니까?
— dacabdi

15

해결책을 찾았 습니다 . 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

문제를 해결합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.