如何从MP4视频中删除或编辑Exif信息?

24

我用三星Galaxy II录制了一段全高清视频,当我上传到YouTube时发现它像竖屏布局1080x1920而不是1920x1080一样旋转了90度。

我找到了问题的原因:

YouTube在编码之前读取视频元数据并根据Exif方向旋转视频

这是ExifTool报告(请查看最后一个标签"Rotation"):

ExifTool版本号:8.61
文件名:video.mp4
目录:。
文件大小:217 MB
文件修改日期/时间:2011:08:11 00:47:23+04:00
文件权限:rw-rw-rw-
文件类型:3GP
MIME类型:video/3gpp
主要品牌:3GPP Media (.3GP) Release 4
次要版本:0.3.0
兼容品牌:3gp4, 3gp6
电影数据大小:227471371
电影头版本:0
创建日期:1900:01:00 00:00:00
修改日期:1900:01:00 00:00:00
时间刻度:1000
长度:0:01:46
首选速率:1
首选音量:100.00%
预览时间:0 s
预览时长:0 s
海报时间:0 s
选择时间:0 s
选择持续时间:0 s
当前时间:0 s
下一跟踪ID:3
跟踪头版本:0
跟踪创建日期:1900:01:00 00:00:00
跟踪修改日期:1900:01:00 00:00:00
跟踪ID:1
跟踪持续时间:0:01:46
跟踪层数:0
跟踪音量:0.00%
图像宽度:1920
图像高度:1080
图形模式:srcCopy
Op颜色:0 0 0
压缩器ID:avc1
源图像宽度:1920 源图像高度:1080 X分辨率:72 Y分辨率:72 位深度:24 视频帧速率:30.023 矩阵结构:1 0 0 0 1 0 0 0 1 媒体头版本:0 媒体创建日期:1900年1月1日 00:00:00 媒体修改日期:1900年1月1日 00:00:00 媒体时间刻度:16000 媒体持续时间:0:01:46 处理程序类型:音轨 处理程序描述:SoundHandler 平衡:0 音频格式:mp4a 音频通道数:1 每个样本的音频位数:16 音频采样率:16000 播放模式:SEQ_PLAY 平均比特率:17.1 Mbps 图像大小:1920x1080 旋转:90
如何删除整个Exif数据或仅编辑旋转属性?
2个回答

43

MP4文件(以及许多其他文件)使用MPEG-4标准,该标准将其内部的数据排列在称为原子的小框中。您可以在此Page找到原子的详细描述。简而言之,原子组织成树状结构,其中一个原子可以是其他原子的父级或数据的容器,但不能同时兼备(尽管有些人打破了这个规则)。

特别地,您要查找的原子称为“tkhd”(Track Header)。您可以在此here找到原子列表。

在此原子中,您将找到视频的元数据。 "tkhd"原子的结构在此here指定。

最后,您需要的元数据块(不是原子)称为“Matrix Structure”。来自developer.apple.com

所有矩阵中的值都是32位定点数,分为16.16,除了{u,v,w}列,它包含32位定点数,分为2.30。
下图显示了此内容:

"Matrix Structure" a transformation matrix

这个9字节的矩阵从"tkhd"原子的第48个字节开始。一个0°方向的"矩阵结构"示例是1 0 0 0 1 0 0 0 1(单位矩阵)。

所以!

经过所有这些,你需要做的就是修改这个矩阵。下一个段落摘自developer.apple.com

变换矩阵定义了如何将一个坐标系中的点映射到另一个坐标系中。通过修改变换矩阵的内容,您可以执行几个标准的图形显示操作,包括平移、旋转和缩放。用于进行二维变换的矩阵可用3x3矩阵进行数学描述。

这意味着变换矩阵定义了一个函数,将每个坐标映射到新坐标。

由于您只需要旋转图像,因此只需修改最左边的2 x 3矩阵,该矩阵由字节0、1、3、4、6和7定义。

以下是我用于表示每个方向的2 x 3矩阵(3x3矩阵的值为0、1、3、4、6和7):

0°:(x',y')=(x,y)
1 0
0 1
0 0

90°:(x', y') = (height-y, x)
0 1
-1 0
height 0 180°:(x', y') = (width-x, height-y)
-1 0
0 -1
width height 270°:(x', y') = (y, width-x)
0 -1
1 0
0 width
如果您没有这些值,可以在矩阵结构之后获取宽度和高度。 它们还是4字节(16.16)的固定点数字。
您的视频元数据很可能包含90°矩阵。
(感谢Exiftool的创建者Phil Harvey提供帮助和出色的软件)

修复一些错误:旋转矩阵由字节0、1、3、4定义。我刚学习了一些带有十六进制转储的3gp文件,宽度和高度可能是无用的。 - twinsant
@twinsant 您需要使用第6和第7个字节来指定旋转函数。例如: 180°:(x',y') = (width - x,height - y) 对于坐标(0,0)(左上角),将被移动到(width,height)(右下角)。 - ignacio.munizaga
1
这很棒,但一些示例代码会非常有帮助!有人可以提供吗? - Sasho
2
有没有适用于Linux的软件可以编辑视频属性? - Redsandro
2
这个答案提供了很好的理论背景。对于实际解决方案,请参见 https://dev59.com/pWkv5IYBdhLWcg3w91hF#31573690 - Bernhard
显示剩余2条评论

1
在我的情况下,更改exif数据并不能解决问题,因为实际上它是正确的。问题在于大多数播放器忽略它(即它们假设它为0)。
如果您确实想要尝试旋转exif标签,则可以通过MediaRecorder.setOrientationHint()来控制它。这比事后修改要容易得多。如果YouTube上传者尊重该标签,则这就是您所需要的。
但我找到的唯一解决方案是旋转视频本身,或使用UI提示引导用户以相机的自然0方向记录视频。
Android中没有内置的旋转视频机制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接