【问题标题】:Extract metadata from multiple videos从多个视频中提取元数据
【发布时间】:2017-06-06 11:41:59
【问题描述】:

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

  • 我有各种类型的视频(以及各种大小写),例如 .mp4、.mov、.MOV、.MP4、.avi、...几乎是非结构化的目录树)。为了找到所有我尝试使用find 命令

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

  • 因此,有了所有这些信息,我必须过滤必填字段值并将它们放入 CSV 文件中。我考虑过使用sed

我的目标是通过脚本或少量单独的命令来完成所有这些任务。

idea代码(这个代码错得离谱,但你可以得到一个idea):

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 时,我感到非常迷失......

提前感谢您的帮助!

【问题讨论】:

  • 你知道mediainfohas--Output=XML参数吗?也许解析 xml 甚至使用它而不是 CSV 会更容易?要使用 xml,您可以使用 xmllint
  • 不知道,它可能确实更容易解析。谢谢。

标签: linux bash video sed metadata


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    试试这个。由于时间太少,我没能完成。您只需将输出发送到 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
    

    【讨论】:

    • 看起来不错。我需要一些时间来深入研究它,并纠正一些细节,但它看起来很有效。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2021-02-26
    • 2019-03-18
    • 2013-07-03
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多