mp4文件修复
Posted yuanbinquan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mp4文件修复相关的知识,希望对你有一定的参考价值。
目录
最近需要在使用mp4录像,mp4录像中不可避免的要直视掉电损坏mp4文件问题。为了解决这个问题各种逛论坛,各种给大神留言,加大神qq,最后因为价格问题被逼只能自己来解决问题。在这个过程中科普了一个mp4文件类型问题。
1、MP4文件类型
标准mp4:MP4 实际代表的含义是 MPEG-4 Part 14。它只是 MPEG 标准中的 14 部分。MP4 主要作用是可以实现快进快放,边下载边播放的效果。他是基于MOV,然后发展成自己相关的格式内容。
fmp4:是基于 MPEG-4 Part 12 的流媒体格式。也有称之为ismv文件的。
2、修复标准mp4思想
基本的mp4概念,h264/h265视频基本概念我这里就不做讲解了,需要了解的兄弟们可以自己去网上了解。
1、 标准mp4文件结构如下:
mp4文件录制过程中,没有完成mp4文件录制,直接掉电会导致moov box数据丢失,moov box的详解了解可以百度查询,moov中心思想就是记录mdat box数据体中音视频裸流数据的数据类型、数据帧偏移地址、数据帧长度等索引信息。所以丢失moov box通用播放器是无法正常解析播放mp4文件的。但是mdat中有掉电前的音视频帧数据,将mdat中的音视频帧数据解析出来然后再封装为完整mp4是修复录像数据的关键。
2、mdat box数据封装
音频帧裸流数据单元(sample)
视频帧长度+视频帧裸流数据单元(sample)
mdat box中的数据都是以流形式写入,一个sample接一个sample存储的,其中视频和音频的差异是:视频数据前面4字节是视频原始数据(视频帧原始数据去掉了h264/h265的00 00 00 01分隔符)长度,长度不包含长度本身4字节,音频数据就没有长度字段。
读取mdat box中的数据后,最为关键的就是区分当前读取数据是视频帧还是音频帧,如果是视频就可以取前4字节指定的长度数据,从而取到一个完整的视频帧。如果是音频帧,音频帧一般都是以固定长度(g711、g726、adpcm)封装的mp4中,取出固定长度的音频帧即为完整的音频帧。然后继续读取mdat数据,区分是视频数据还是音频数据,直到mdat数据分析完成。将分组的音频+视频再打包为mp4,即可完成mp4文件的修复。
3、mdat box中音视频帧区分
这里只说方法,不讲具体实现。有兴趣的伙伴自己去实现吧!!
写入mp4时,将每一帧音视频数据的:帧类型、帧长度、帧数据前16直接打印出来。然后mp4写到一半时突然拔掉sd卡,拿出损坏的mp4文件和打印信息对比分析mdat,就知道如何区分mdat中的音、视频数据了,进而实现mp4文件修复。
3、mp4修复验证平台
ARM+libmp4v2+h265+g711_a
如何获取音频文件的准确时长,比如MP3
用过mciSendCommand(wDevice,MCI_STATUS,MCI_STATUS_ITEM, (DWORD) (LPMCI_STATUS_PARMS)&StatusParms);可是获取的时长有时不准确,我一个MP3文件明明是1分钟,可是用这个方法得到的是4分钟 ,请问还有其他方法能够得到准确的时长信息吗?
我用同样的代码,在另外一台电脑上运行却可以获取真实时长,不知是哪里出的问题,请高手指教
@ echo off
>"%tmp%\a.js" echo var f=new ActiveXObject("Shell.Application").NameSpace("D:\\新建文件夹");
>>"%tmp%\a.js" echo WSH.echo(f.GetDetailsOf(f.ParseName("a.mp3"),21));
for /f %%i in ('cscript //nologo "%tmp%\a.js"') do echo %%i
pause 参考技术B mp3的话,右键属性里的详细信息里有写,一般也不会有错追问
我指的是用编程的方法获取“时长”这个信息 用在程序里的,并不是看一眼就算了
以上是关于mp4文件修复的主要内容,如果未能解决你的问题,请参考以下文章
Raspberry Pi 4 中的 mp4 编解码器:不将帧写入视频