ffmpeg会破坏bash的while循环

我想要用这段脚本批量把视频用h265压一遍,但while循环只走第一遍
vfiles.txt是放要压缩的视频文件的,有很多行
试过注释掉ffmpeg,然后循环就能正常走完多遍

function get_filename_from_path()
{
    echo ${1##*/}
}
function remove_filename_from_path()
{
    if [[ "$1" =~ '/' ]]; then
        echo ${1%/*}
    else
        echo ""
    fi
}
function remove_filename_suffix()
{
    echo "${1%.*}"
}

DEST_F="$1"
shift
echo "Destination: $DEST_F"

while read line ; 
do

    filename_full=$(get_filename_from_path "$line")
    filename=$(remove_filename_suffix "$filename_full")
    PSOURCE=$(remove_filename_from_path "$line")
    mkdir -p "$DEST_F/$PSOURCE"
    echo "Converting $line"
    
    ffmpeg -hide_banner -i "$line" \
        -c:v libx265 -c:a aac -preset veryslow \
        "$DEST_F/$PSOURCE/$filename.mkv"
    
    echo -n Convertion done $(du -k "$line" | cut -f1)k
    echo -n " -> "
    echo $(du -k "$DEST_F/$PSOURCE/$filename.mkv" | cut -f1)k

done < vfiles.txt

:confused:

没用 -x 调试看看么?

我发现很可能是ffmpeg内存泄漏之类的影响到bash了

第一遍的循环压制了一个视频后,有时直接跳了vfiles.txt几行跑第二遍,而且第二遍的文件名中文读出来有乱码。
有时第二遍直接把脚本最后一行的done读成one,bash报错

不跑ffmpeg就都没那些问题

当然,也可能是bash有内存泄漏的bug之类
我现在用的是15.1
:slightly_frowning_face:

你那儿出了啥问题我不知道,我就知道我直接用你脚本随便测试了一两个含有中文且命名较为复杂的 youtube-dl 命名格式视频文件,ffmpeg 蹦出了一堆不可读又看不懂的东西,最后以 xx No such file or directory 错误退出,而那个 xx 确实不存在,属于之后的某个序列文件名的一部分……

跑了跑 shellcheck 确定了应该和各种变量的神奇扩展有关,跟着建议改了改(就大概加了几个引号避免非预期扩展
跑了几个文件,感觉没啥问题了。

function get_filename_from_path()
{
    echo "${1##*/}"
}
function remove_filename_from_path()
{
    if [[ "$1" =~ '/' ]]; then
        echo "${1%/*}"
    else
        echo ""
    fi
}
function remove_filename_suffix()
{
    echo "${1%.*}"
}

DEST_F="$1"
shift
echo "Destination: $DEST_F"

while read -r line ; 
do

    filename_full=$(get_filename_from_path "$line")
    filename=$(remove_filename_suffix "$filename_full")
    PSOURCE=$(remove_filename_from_path "$line")
    mkdir -p "$DEST_F/$PSOURCE"
    echo "Converting $line"
    
    ffmpeg -nostdin -hide_banner -i "$line" \
        -c:v libx265 -c:a aac -preset veryslow \
        "$DEST_F/$PSOURCE/$filename.mkv"
    
    echo -n "Convertion done $(du -k "$line" | cut -f1)k"
    echo -n " -> "
    echo "$(du -k "$DEST_F/$PSOURCE/$filename.mkv" | cut -f1)k"

done < vfiles.txt

BTW,写 shell 脚本之后跑跑 shellcheck 不应该是常规操作的么

1赞

用了你帮我改的可以了,太谢谢了

还有一点很奇怪,之前试过ffmpeg之后加>/dev/null 2>&1,问题还在
难道有一些ffmpeg输出的特殊符号是无法用重定向消灭的?
还是说后面的echo+du产生什么问题?

不用 -nostdin 直接丢掉所有输出,在我这儿测试(跑了一个文件)确实可行,没有其他改动,不要 ffmpeg 单独跑也能行……不清楚你重定向之后遇到的具体问题是啥

其他的引号啥的问题,在某些特定场景下确实会有暗坑,还是尽可能避免的好

写 shell 脚本配合 shellcheck 食用确实能避免遇到很多可以不遇到的问题,如果没用可以试试

本主题在最后一个回复创建后60分钟后自动锁定。不再允许添加新回复。