从多个视频中提取元数据

时间:2017-06-06 11:42:00

标签: linux bash video sed metadata

我面临着需要bash多个方面的挑战。我在Linux(恰好是Debian Stretch)工作。这是情况(对于我现在考虑的解决方案所写的所有问题/问题,但我对其他想法持开放态度):

  • 我有各种类型的视频(以及各种大写小写),例如.mp4,.mov,.MOV,.MP4,.avi,...位于目录中(并分布在一个目录中)几乎没有结构的目录树)。要查找我尝试使用find命令

  • 的所有内容
  • 对于每个视频,我需要提取一些元数据(即文件名,视频持续时间,文件大小和创建日期/上次修改)。包mediainfo产生(在许多其他事物中)必需的字段。 mediainfo的输出是一长串字段列表,格式为:<Tag>\t : <value>。我需要提取字段完整名称持续时间文件大小编码日期的值。

  • 所有这些信息,我必须过滤所需的字段值并将它们放在CSV文件中。我考虑过使用sed

我的目标是在脚本或少量单独的命令中实现所有这些任务。

想法代码(这段代码非常糟糕,但你可以得到一个想法):

find . -type f -name "*.[mp4|MP4|mov|MOV|avi|AVI]" -exec mediainfo {} | sed '/Complete name|Duration|File size|Encoded date/p' > myfile.csv \;

您是否知道如何执行此任务?在将find,exec和sed以及输出组合到csv中时,我感到非常失落......

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

所以我终于设法写了一个脚本。可能不是最好的方法,但这里是:

resFile="myresult.csv"
dstDir="./destination/"
srcDir="./source/"

#first copy all files at same level in dstDir (with preserve and update)
#this is somehow necessary, relative name for MOV files and mediainfo 
#do not seem to work together.
find $srcDir -type f \( -name "*.mp4" -o -name "*.mov" -o -name "*.MOV" -o -name "*.avi" \) -exec cp -up {} $dstDir \;

#then for each file, output mediainfo of file and keep only interesting tags. add ### between each file.
find $dstDir -type f \( -name "*.mp4" -o -name "*.mov" -o -name "*.MOV" -o -name "*.avi"\
    -exec sh -c " mediainfo --Output=XML {} | sed '1,15!d;/Duration\|Complete\|File_size\|Encoded_date/!d' >> $resFile && echo '########' >> $resFile" \; 

#removes tags : <Duration>42s 15ms</Duration> -> 42s 15ms
sed -i 's/^<.*>\(.*\)<.*>/\1/I' $resFile

#Extract exact filename (and not relative)
sed -i 's/^\.\/.*\/\(.*\)\.[mp4|MOV|mov|avi|MP4]/\1/' $resFile

#Puts fields for a file on a unique line separated with commas
sed -i 'N;s/\n/,/;N;s/\n/,/;N;s/\n/,/;N;s/\n/,/' $resFile

#remove all trailing ###
sed -i 's/,#*$//' $resFile

如果有人想改进代码,我仍然会感兴趣。 我“最小化”了一点,我的实际代码更模块化并执行一些检查

答案 1 :(得分:-1)

试试这个。由于时间较少,我无法完成。您只需将输出发送到CSV。

for c in $(locate --basename .mp4 .mkv .wmv .flv .webm .mov .avi)

do

 Complete_name=$(mediainfo --Output=XML $c | xml_grep 'Complete_name' --text_only| awk 'BEGIN{FS="/"}{print $NF}')

    echo $Complete_name

 Duration=$(mediainfo --Output=XML $c | xml_grep 'Duration' --text_only --nb_result 1)

    echo $Duration

 File_size=$(mediainfo --Output=XML $c | xml_grep 'File_size' --text_only)

echo $File_size

Encoded_date=$(mediainfo --Output=XML $c | xml_grep 'Encoded_date' --text_only -nb_result 1 | awk '{print $2}')

echo $Encoded_date

done