谁能告诉我这样做哪里错了。
这个想法是找到目录中的所有文件并将其转换为 m4v。无论扩展名是什么。然后,一旦转换完成,就从转换后文件中所谓的“相关”部分生成缩略图。然后,一旦完成,就删除原始文件(理想情况下,如果它比原始文件小 - 但是我还没有弄清楚这一点。)我对 shell 脚本非常陌生,所以任何帮助都将不胜感激。
然后我希望将来能将文件名和详细信息添加到 MySQL 数据库中。如果有人对此有任何建议,我将不胜感激。此外,如何添加检查以跳过已经是 m4v 的文件的转换。
#!/bin/bash
#Convert files using ffmpeg
OrDir="/Volumes/Misc/Test/"
NewDir="/Volumes/Misc/Conv2/"
find "$OrDir" -type f -exec /bin/bash -c \
'f2=$(basename "$1"); \
ffmpeg -i "$1" -c:v libx264 -crf 23 -preset ultrafast -c:a aac -strict experimental -b:a 192k -ac 2 "${NewDir}${f2%.*}.m4v" ' _ {} \;
ffmpeg -ss 3 -i "${NewDir}${f2}.m4v" -vf "select=gt(scene\,0.4)" -frames:v 5 -vsync vfr fps=fps=1/600 "${NewDir}pictures/${f2%.*}.jpg"
rm $1
更新: 在过去的几天里,我一直在研究这个问题,目前我得到的结果是:
#!/bin/bash
#Convert files using ffmpeg
OrDir="/Volumes/Misc/Test"
find "$OrDir" -type f -exec /bin/bash -c \
'ND="/Volumes/Misc/Convert/"
f2=$(basename "$1")
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width "$1")
size=${streams_stream_0_height}
if [ "$size" -gt 720 ]
then
size=720
fi
ffmpeg -y -hide_banner -i "$1" -codec:v libx264 -profile:v high -preset ultrafast -b:v 500k -qmin 10 -qmax 42 -maxrate 1000k -bufsize 1000k -threads 0 -vf "scale=-1:$size" -pass 1 -c:a aac -strict -2 -b:a 128k -f m4v /dev$
ffmpeg -y -hide_banner -i "$1" -codec:v libx264 -profile:v high -preset ultrafast -b:v 500k -qmin 10 -qmax 42 -maxrate 1000k -bufsize 1000k -threads 0 -vf "scale=-1:$size" -pass 2 -c:a aac -strict -2 -b:a 128k "$ND${f2%.*$
ffmpeg -hide_banner -i "$ND${f2%.*}.m4v" -vf "select=gt(scene\,0.4), scale=-1:135, fps=1/60" -frames:v 5 -vsync vfr "${ND}pictures/${f2%.*}_%03d.png"
rm $1
mysql --host=****** --user=***** --password=****** db << EOF
INSERT INTO tbl (Name, FileType, Time, AddedDate) VALUES ("${f2%.*}", '.m4v', 0, NOW());
EOF
' _ {} \;
这有两个问题;首先,它并不总是生成缩略图,有时会返回,Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)
但创建的文件转换完美;其次,mysql 行没有正确执行并返回错误:_: line 12: mysql: command not found
我还没有弄清楚如何获取视频的持续时间,以便将其也添加到数据库中。
答案1
如果您打算扩展这个脚本(从您关于数据库的问题来看),我建议您尽可能地进行参数化。
我还建议使用ffmpegthumbnailer
生成缩略图,这应该很简单yum install ffmpegthumbnailer
。apt-get install ffmpegthumbnailer
检查选项 - 在我的脚本中,我生成-s0
与原始大小相同的缩略图(),但您可能不想要这样。
这个示例脚本应该可以帮助你入门:
#!/bin/bash
# Convert files using ffmpeg
# USE AT YOUR OWN RISK!
# Parameters
OrDir="/tmp/video/" # Original directory
NewDir="/tmp/video/out/" # New directory
PicsDir=${NewDir}pictures/
ignore="m4v" # ignore single filetype being converted
convto="$ignore" # in case you want to convert to something else
thumbnailseek=5 # Seek % at which to generate thumbnail
# Change to original directory
# For each file:
# check appropriate (exists, not directory, not already same type)
# convert to $convto type media file (ffmpeg)
# generate thumbnail (ffmpegthumbnailer)
# (optional) remove original if new version smaller
cd "$OrDir"
for oldfile in *.mkv; do # indeed every file; globbing will eat up spaces properly
ext=${i##*.}
# ignore 1) non-existant files 2) directories 3) $ignore-extentioned files
if [[ ! -e "$oldfile" ]] || [[ -d "$oldfile" ]] || [[ "$ext" = "$ignore" ]]; then
continue
fi
filename=${oldfile%.*}
newfile="$NewDir$filename.$convto"
oFS=$(stat --printf="%s" $oldfile) # old file size
ffmpeg -y -loglevel quiet -i "$oldfile" -c:v libx264 -crf 23 -preset ultrafast -c:a aac -strict experimental -$
nFS=$(stat --printf="%s" $newfile) # new file size
ffmpegthumbnailer -s0 -i "$newfile" -t $thumbnailseek -o "$PicsDir$filename.jpg" &>/dev/null
if [ "$oFS" -gt "$nFS" ]; then
#rm -- "$OrDir$oldfile" # AT OWN RISK: uncomment to remove older file if smaller
fi
done
我不是专家,只要仔细阅读上述代码就会发现这一点。我将自己的变量命名约定与原始代码中的约定混合在一起(我的目的是保持一定的熟悉度);我可以进一步参数化;我在脚本中编入了相当多的假设(例如,OrDir
只包含视频文件);一些条件测试可以简化;文件名和目录处理可以统一。
但这不是代码审查。不应该有任何明显的错误,并且它可以在一些我一直在等待的 mkv 上本地运行,就为了等待这样的事情。
如果你打算用 bash 脚本做更多的事情,那么值得阅读一些常见的 bash 陷阱,如果你有时间高级 Bash 脚本指南。
对于“SQL 数据库”,需要更多信息才能提供任何建议。什么类型的数据库?SQLite?为什么要使用 SQL,而不是简单的平面文件(CSV 等)?有哪些详细信息?