一、提取每个关键帧对应的时间点
1、dump MP4文件的atom信息
$ MP4Box -diso 129066073816865d76fac2.mp4
生成大小9.3M的xml文件129066073816865d76fac2_info.xml
2、拆分视频部分供计算关键帧的位置大小
获取视频部分的起止行号
$ cat -n 129066073816865d76fac2_info.xml|grep "trak"|awk '{print $1}'
30
125426
$ cat -n 129066073816865d76fac2_info.xml|awk 'NR>=30&&NR<=125426'>129066073816865d76fac2_info_video.xml
拆分出6.3M的 129066073816865d76fac2_info_video.xml
3、取sample的时间增量SampleDelta
$ cat -n 129066073816865d76fac2_info_video.xml |grep "TimeToSampleEntry"|awk -F /" '{print $2}'
1000
4、取视频的TimeScale值(每秒钟的时间刻度)
$ cat -n 129066073816865d76fac2_info_video.xml |grep "TimeScale"|awk -F /" '{print $6}'
25000
5、取关键帧序号并计算关键帧对应的时间点
$ more 129066073816865d76fac2_info.xml |grep "SyncSampleEntry sampleNumber"|awk -F /" '{print $2 *1000/25000}'
6、结果比用flash提取的每个关键帧时间点推后0.04s,原因是flash提取时认为第一个关键帧的时间点是第0s,而MP4的atom中记录的是第0.04s。提取一集250MB电视剧瞬间完成。
二、提取每个关键帧对应的位置大小
1、提取视频的sample和chunk对应关系表SampleToChunkBox
$ more 129066073816865d76fac2_info_video.xml|grep "SampleToChunk"|grep -v "SampleToChunkBox"|awk -F /" '{print $2" "$4}'>SampleToChunk.txt
2、提取chunk的offset对应表ChunkEntryoffset
$ more 129066073816865d76fac2_info_video.xml|grep "ChunkEntry offset"|awk -F /" '{print $2}'>ChunkEntryoffset.txt
3、提取sample大小对应表SampleSize
$ more 129066073816865d76fac2_info_video.xml|grep "SampleSizeEntry"|awk -F /" '{print $2}'>SampleSize.txt
4、根据SampleToChunkBox表的累加求和计算出每个关键帧所在的chunk及所在chunk中的第几个sample,然后参考ChunkEntryoffset表和SampleSize表计算出该关
键帧的大小。
5、结果比用flash提取的每个关键帧的位置大小大40B。120测试用php程序提取一集250MB电视剧需1.5分钟完成,运行时cpu占用50%左右。
优化后的脚本:
# more gettimes.sh
#!/bin/bash
filedir=/data/videos/
opdir=/backup/getmetadata/gettimes/
filename1=1291250932041f4cb679c
filename2=12912605280909b66e6efd
filename3=12916204660743391cc2b9
filename4=129177303021252fb62c40
filename5=129125093204263f076b80
filename6=129126052809163f4916a7
filename7=12916204660797033a9882
filename8=1291773030212e5dc9a57
filename9=1291250932042cdbcf8a2
filename10=12912605280924ceaab531
fix=.mp4
xmlfix=_info.xml
xmlvideofix=_info_video.xml
timesfix=_times.txt
syncsample=_SyncSample.txt
sampletochunk=_SampleToChunk.txt
chunkoffset=_ChunkEntryoffset.txt
samplesize=_SampleSize.txt
sampledelta=_SampleDelta.txt
timescale=_TimeScale.txt
for filename in $filename1 $filename2 $filename3 $filename4 $filename5 $filename6 $filename7 $filename8 $filenam
e9 $filename10 ; do
MP4Box -diso $filedir$filename$fix
mv $filedir$filename$xmlfix $opdir$filename$xmlfix
##截取视频部分
videostartpart=$(cat -n $opdir$filename$xmlfix |grep "<TrackBox>" |awk '{print $1}'|awk 'NR==1')
videoendpart=$(cat -n $opdir$filename$xmlfix |grep "</TrackBox>"|awk '{print $1}'|awk 'NR==1')
cat -n $opdir$filename$xmlfix |awk '{if(NR>='$videostartpart'&&NR<='$videoendpart') print $0}'|grep -v "
CompositionOffsetEntry">$opdir$filename$xmlvideofix
##计算关键帧的时间点
cat -n $opdir$filename$xmlvideofix|grep "TimeToSampleEntry"|awk -F /" '{print $2}'>$opdir$filename$sampl
edelta
cat -n $opdir$filename$xmlvideofix |grep "TimeScale"|awk -F /" '{print $6}'>$opdir$filename$timescale
SampleDelta=$(cat -n $opdir$filename$xmlvideofix|grep "TimeToSampleEntry"|awk -F /" '{print $2}')
TimeScale=$(cat -n $opdir$filename$xmlvideofix |grep "TimeScale"|awk -F /" '{print $6}')
cat -n $opdir$filename$xmlvideofix|grep "SyncSampleEntry"|awk -F /" '{print $2 *'$SampleDelta'/'$TimeSc
ale'-0.04}'>$opdir$filename$timesfix
##提取供计算position的数据
cat -n $opdir$filename$xmlvideofix|grep "SyncSampleEntry"|awk -F /" '{print $2}'>$opdir$filename$syncsa
mple
cat -n $opdir$filename$xmlvideofix|grep "SampleToChunkEntry"|awk -F /" '{print $2" "$4}'>$opdir$filename
$sampletochunk
cat -n $opdir$filename$xmlvideofix|grep "ChunkEntry offset" |awk -F /" '{print $2}'>$opdir$filename$chun
koffset
cat -n $opdir$filename$xmlvideofix|grep "SampleSizeEntry" |awk -F /" '{print $2}'>$opdir$filename$samp
lesize
rm $opdir$filename$xmlfix
rm $opdir$filename$xmlvideofix
done