MP4文件中的XMP元数据长度异常

1.起因

发现线上的一个视频,客户端播放正常,却无法缓存。

分析缓存文件,发现始终有一段数据,没有缓存成功。

客户端缓存方案使用的是AVAssetResourceLoaderDelegate(JPVideoPlayer)方案,

进一步排查,断点跟踪发现,AVPlayer发起的 AVAssetResourceLoadingRequest数据请求,并没有包含缺失的数据段,但是播放没有发现任何异常。

改用HttpServer(KTVHTTPCache)方案,也无法完整缓存视频文件。

怀疑MP4文件可能嵌入一段跟播放无关的数据?

2.MP4文件格式解析

简单学习了
FFmpeg使用手册 – MP4的格式解析

  1. MP4文件由许多个Box与FullBox组成
  2. 每个Box由Header和Data两部分组成
  3. FullBox则是Box的扩展,Box结构的基础上在Header中增加8bit位 version标志和24bit位的flags标志
  4. Header包含了整个Box的长度的大小(Size)和类型(Type),当size等于0时,代表这个Box是文件的最后一个Box;当size等于0时说明Box长度需要更多的bits位来描述,在后面会定义一个64bits位的largesize用来描述Box的长度;当Type为uuid时,说明这个Box中的数据是用户自定义扩展类型;
  5. Data为Box的实际数据,可以是纯数据也可以是更多的子Box;
  6. 当一个Box中Data是一系列的子Box时,这个Box又可以称作为Container Box。

使用工具MediaParser(Mac版的mp4info) 分析视频文件,如图:

确实存在一段自定义的Box,offset与缓存缺失的数据段基本一致,size居然达到2MB多。目测这段数据与XMP元数据有关(这个工具只显示了前4096B的数据)

3.使用 Adoub Media Encoder CC 2015 重新导出视频

元数据导出选项->无,也就是不导出元数据到视频文件中,然后对比前后两个视频,size缩小了,画质等等均无变化,进一步验证XMP元数据不影响播放。

4.异常的XMP元数据到底是什么呢?

ffprobe 1.mp4 -show_entries stream_tags=XMP -print_format json -export_xmp 1

使用ffprobe解析MP4文件,终于发现了异常数据, photoshop:DocumentAncestors 有大约35000条记录,Ps操作记录?

5.分享下脚本

#!/bin/sh

#  export_mp4_xmp.sh
#  NurseryRhyme
#
#  Created by shixiaoda on 2020/2/1.
#  Copyright © 2018年 BabyBus. All rights reserved.
#项目路径
assetsPath=""
desPath="$(pwd)/../XMP"
echo "====================开始导出XMP===================="
echo "mp4文件目录:$(pwd)/${1-$assetsPath}"
echo "XMP文件目录:${desPath}"
echo "过滤条件:文件size大于${2-0}kB"
echo "==================================================="
mp4filenum=0
XMPnum=0
function export_xmp(){
    for element in `ls $1`; do
        dir_or_file=$1"/"$element
        if [ -d $dir_or_file ]; then
            # if [$dir_or_file != ]
            export_xmp $dir_or_file ${2-0}
        else
            if [[ "${dir_or_file##*.}"x = "mp4"x ]]; then
                let mp4filenum+=1
                # echo "find mp4 file ---> $dir_or_file"
                filename=${dir_or_file##*/}
                # echo ${filename%.*}
                filepath=${desPath}/${filename%.*}
                # echo ${filepath}
                # json格式导出XMP
                ffprobe ${dir_or_file} -show_entries stream_tags=XMP -print_format json -export_xmp 1 &>${filepath}
                # 计算XMP文件大小
                filesize=`ls -l $filepath | awk '{print $5}'`
                maxsize=`expr $2 \* 1024`
                if [ $filesize -gt $maxsize ]; then
                    filesizeMB=`expr $filesize / 1024`
                    let XMPnum+=1
                    echo "export XMP $filesizeMB kB ---> $filepath"
                else
                    rm -rdf "${filepath}"
                fi
            # else
                # echo "skip other type file ---> $dir_or_file"
            fi
        fi
        # break
    done
}
rm -rdf "${desPath}"
mkdir "${desPath}"
export_xmp "$(pwd)/${1-$assetsPath}" ${2-0}
echo "====================XMP导出完毕😎===================="
echo "mp4文件数:                   $mp4filenum"
echo "大于${2-0}kB的XMP文件数:    $XMPnum"
exit

6.参考

  1. mp4文件解析
  2. 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频。
  3. MP4文件格式的解析,以及MP4文件的分割算法
  4. Media Encoder 的导出设置参考
  5. XMP Data No longer showing using FFPROBE – FFmpeg

https://juejin.im/post/5e36725e5188254d9032aabc

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论