【发布时间】:2019-10-14 08:58:22
【问题描述】:
想使用脚本将我的 m4a 文件转换为 mp3 文件。这会节省一些时间...我有超过 100 GB 的音乐文件。
操作系统:OSX10.14 / 终端与 Bash 脚本
我可以从终端运行ffmpeg -v 5 -y -i musicFile.m4a -acodec libmp3lame -ac 2 -b:a 320k musicFile.mp3。它会转换文件,我可以从 iTunes 中查看和播放文件。
当我从 bash 脚本运行相同的脚本时,它无法转换。
ffmpeg -v 5 -y -i $ENTRY_FILE -acodec libmp3lame -ac 2 -b:a 320k $MP3NAME
我的 ipod nano 刚刚死了,我得到了一个新的 mp3 播放器。现在我需要将我的 iTunes 文件从 AAC 格式转换为 MP3。 ffmpeg 是一个成熟的视频和音乐文件转换器。
当我从 bash 脚本运行它时,我尝试了一些方法。
我在文件前面加了./,失败是因为它安装在/usr/local/bin下,而不是在同一个目录下。
我也尝试了 sh ffmpeg...,这让我无法执行二进制文件。
#!/usr/bin/env bash
# convert m4a file to mp3
set -e
file_convert() {
ENTRY_FILE=$(printf %q "${entry}")
FILE_NAME=$(printf %q "$(basename "${entry}")")
DIR=$(printf %q "$(dirname "${entry}")")
NAME="${FILE_NAME%.*}"
EXT="${FILE_NAME##*.}"
MP3NAME="${DIR}/${NAME}.mp3"
printf "%*s%s\n" $((indent+2)) '' "$ENTRY_FILE"
printf "%*s\tNew File :\t%s\n" $((indent+2)) '' "$MP3NAME"
if [ $EXT == "m4a" ]
then
printf "%*s\tConverting: \t%s\n" $((index+2)) '' "$ENTRY_FILE"
ffmpeg -v 5 -y -i $ENTRY_FILE -acodec libmp3lame -ac 2 -b:a 320k $MP3NAME
fi
}
walk() {
local indent="${2:-0}"
printf "\n%*s%s\n\n" "$indent" '' "$1"
# If the entry is a file convert it
for entry in "$1"/*; do [[ -f "$entry" ]] && file_convert; done
# If the entry is a directory recurse
for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+2)); done
}
# If the path is empty use the current, otherwise convert relative to absolute; Exec walk()
[[ -z "${1}" ]] && ABS_PATH="${PWD}" || pushd "${1}" && ABS_PATH="${PWD}"
walk "${ABS_PATH}"
popd
echo
我希望>./aacToMp3.sh ./music 遍历音乐目录并将每个 m4a 文件转换为 .mp3。
它正在遍历文件系统并打印出正确的文件,其中空格已转义。当它到达 ffmpeg 行时,它会停止。如果命令失败,我将 set -e 放在文件顶部以强制它失败。如果没有 set -e,它会愉快地遍历所有音乐文件并将它们打印到标准输出。
【问题讨论】:
-
在调用
ffmpeg之前放置echo $ENTRY_FILE和echo $MP3NAME并验证它们是否在 ffmpeg 到达之前获得了正确的值 -
引用变量。
-
到达
ffmpeg行时会出现什么错误? -
您的两个
for entry循环应该是一个包含if/elif测试的for循环。这将防止每个目录的内容被扫描两次。避免链接&&和||的诱惑 - 改用if块。永远不要使用set -e。您可以使用set -x来跟踪执行情况并向您显示变量是否获得了您期望的值。 -
@MarkSetchell,仅供参考,这里不需要 GNU Parallel,使用
xargs -P应该能够实现相同的目标。