Eu tenho um script bash percorrendo os resultados de uma localização e executando uma codificação ffmpeg de alguns arquivos FLV. Enquanto o script está sendo executado, a saída do ffmpeg parece estar interrompida e está gerando alguns erros de aparência estranha, como o abaixo. Não tenho ideia do que está acontecendo aqui. Alguém pode me apontar na direção certa?
É como se o loop ainda estivesse em execução quando não deveria estar e interrompendo o processo ffmpeg.
O erro específico é:
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'
Mais alguns detalhes da saída 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'
O script é o seguinte
#!/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)
pode ser útil (verman basename
eman dirname
para mais informações)bash -x myscript
para obter um rastreamento linha por linha da execução do script, com todas as variáveis expandidas. Ah, e aliás, você reinventou abasename
roda naFILENAME=
linha. :)Respostas:
Sua pergunta é realmente Bash FAQ # 89 : basta adicionar
</dev/null
para impedir affmpeg
leitura de sua entrada padrão.Tomei a liberdade de corrigir seu script para você, pois ele contém muitos erros em potencial. Alguns dos pontos importantes:
Os nomes de arquivos são difíceis de manipular, porque a maioria dos sistemas de arquivos permite que eles contenham todos os tipos de caracteres não imprimíveis que as pessoas comuns veriam como lixo. Fazer suposições simplificadoras como "nomes de arquivos contêm apenas caracteres 'normais'" tende a resultar em scripts de shell frágeis que aparecempara trabalhar em nomes de arquivos "normais" e depois quebrar o dia em que eles se deparam com um nome de arquivo particularmente desagradável que não segue as suposições do script. Por outro lado, o manuseio correto dos nomes dos arquivos pode ser tão incômodo que você pode achar que não vale a pena se a chance de encontrar um nome de arquivo estranho estiver próxima de zero (ou seja, você só usa o script em seus próprios arquivos e você atribui aos seus próprios arquivos nomes "simples"). Às vezes, é possível evitar completamente essa decisão não analisando os nomes dos arquivos. Felizmente, isso é possível com
find(1)
a-exec
opção. Basta colocar{}
o argumento em-exec
e você não precisa se preocupar em analisar afind
saída.Usar
sed
ou outros processos externos para executar operações simples de cadeia, como remover extensões e prefixos, é ineficiente. Em vez disso, use expansões de parâmetros que fazem parte do shell (nenhum processo externo significa que será mais rápido). Alguns artigos úteis sobre o assunto estão listados abaixo:Use
$( )
e não use``
mais: Bash FAQ 82 .Evite usar nomes de variáveis UPPERCASE. Esse espaço para nome é geralmente reservado pelo shell para fins especiais (como
PATH
), portanto, usá-lo para suas próprias variáveis é uma má idéia.E agora, sem mais delongas, aqui está um script limpo para você:
Nota: Eu usei o POSIX
sh
porque você não usava ou não precisava de nenhumbash
recurso específico no original.fonte
zsh
. Talvez algumas pessoas do zsh no site saibam.Eu encontrei a solução . O script bash parece produzir entrada (a chave 'c') que interfere no
ffmpeg
processo.Adicionando
< /dev/null
àffmpeg
linha de comando, assim:corrige o problema.
fonte