将 360 元数据注入 .mp4 文件

Tru*_*CP5 5 c# video mp4 metadata ffmpeg

我正在开发一个库,它将元数据注入 .mp4 文件,以允许视频正确显示为 360 度视频。输入文件是等距柱状投影格式的标准 .mp4 文件。我知道需要注入哪些元数据,但我只是不知道如何注入它。

我花了一些时间寻找可以做到这一点的库,但只能找到用于提取元数据而不是注入/嵌入/写入元数据的库。我发现的替代方案是使用Spatial Media作为命令行应用程序来更轻松地注入元数据。问题是我对 python 的了解为零,所以我倾向于使用库/nuget 包/ffmpeg 脚本。

是否存在一个好的 nuget 包/库可以做到这一点,或者我应该选择替代选项?

编辑1

我尝试将元数据粘贴到文件中的正确位置,以防万一它可以工作,但它没有。

编辑2

这是谷歌空间媒体工具注入的元数据,这就是我想要实现的目标:

<?xml version="1.0"?><rdf:SphericaVideo
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:GSpherical="http://ns.google.com/videos/1.0/spherical/"><GSpherical:Spherical>true</GSpherical:Spherical><GSpherical:Stitched>true</GSpherical:Stitched><GSpherical:StitchingSoftware>Spherical Metadata Tool</GSpherical:StitchingSoftware><GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType></rdf:SphericalVideo>`
Run Code Online (Sandbox Code Playgroud)

编辑3

我也尝试过使用 ffmpeg 来做到这一点,如下所示:ffmpeg -i input.mp4 -movflags use_metadata_tags -metadata Spherical=true -metadata Stitched=true -metadata ProjectionType=equirectangular -metadata StitchingSoftware=StreetviewJourney -codec copy output.mp4

我认为 ffmpeg 方法的问题在于它不包含rdf:SphericalVideo允许使用球形视频标签的部分。

编辑4

当我使用 ffmpeg 提取元数据时,它在日志中包含球形标记,但当我将其输出到 ffmetadata 文件时则不包含球形标记。这是我使用的命令:ffmpeg -i injected.mp4 -map_metadata -1 -f ffmetadata data.txt

这是日志的输出:

 fps, 60 tbr, 15360 tbn, 120 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Side data:
      spherical: equirectangular (0.000000/0.000000/0.000000)
Run Code Online (Sandbox Code Playgroud)

编辑5

我还尝试使用以下命令获取元数据:ffprobe -v error -select_streams v:0 -show_streams -of default=noprint_wrappers=1 injected.mp4

这是它输出的日志:

TAG:handler_name=VideoHandler
side_data_type=Spherical Mapping
projection=equirectangular
yaw=0
pitch=0
roll=0
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用这个命令,但它不起作用:ffmpeg -i chapmanspeak.mp4 -movflags use_metadata_tags -metadata side_metadata_type="Spherical Mapping" -metadata projection=equirectangular -metadata yaw=0 -metadata pitch=0 -metadata roll=0 -codec copy output.mp4

编辑6

我尝试了@VC.One的方法,但我一定做错了什么,因为输出文件无法播放。这是我的代码:

 fps, 60 tbr, 15360 tbn, 120 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Side data:
      spherical: equirectangular (0.000000/0.000000/0.000000)
Run Code Online (Sandbox Code Playgroud)

字节被反转,因为 .mp4 似乎是 Little Endian。我也尝试更新长度,trak但这也不起作用。

VC.*_*One 2

简洁版本:

  • 您的元数据长度为 454 字节。

  • 在atom的末尾添加元数据trak

  • trak通过将其显示值增加 来更新 的大小+ 454

  • moov通过将其显示值增加 来更新 的大小+ 454

  • 通过将其值增加 来查找stco并更新列出的每个项。Offset entry+ 454

然后测试视频文件作为 Youtube 上传。这是我在 YouTube 上的示例

长版:

“我尝试将元数据粘贴到文件中的正确位置”

这不起作用,因为它会替换(或推送)音频/视频数据的字节。A/V 数据的这些字节位置存储在 MP4 标头中,因此如果您在其中添加任何新字节,您还必须更新依赖于一些先前正确的偏移量来显示帧的其他部分。

我不确定您将哪一部分称为“正确的位置”(哪个 Atom?在哪个 Box 下?)。
无论您做什么,添加元数据字节后,都必须更新、的大小,以及列出的偏移量,并且每个偏移量都必须通过将元数据的字节长度添加到值来增加。 MOOVTRAKSTCO

您的元数据的长度为:454字节。
这意味着尺寸偏移量必须更新为:This_Atom_Value += 454;

“我知道需要注入哪些元数据,但我只是不知道如何注入它。”

可能的解决方案:这就是我为了让它在 Youtube 上运行而所做的......

1)首先确保元数据正确(不仅是文本,而且是字节/十六进制格式)。

例如,在您的第一行中,“Spherical”中缺少“l”,因此它不起作用。

  • 你说:<rdf:SphericaVideo..xmlns
  • 正确的:<rdf:SphericalVideo.xmlns

正确的元数据 XML 是:

<?xml version="1.0"?><rdf:SphericalVideo.xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#".xmlns:GSpherical="http://ns.google.com/videos/1.0/spherical/"><GSpherical:Spherical>true</GSpherical:Spherical><GSpherical:Stitched>true</GSpherical:Stitched><GSpherical:StitchingSoftware>Spherical Metadata Tool</GSpherical:StitchingSoftware><GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType></rdf:SphericalVideo>
Run Code Online (Sandbox Code Playgroud)

以下是上述元数据文本的正确字节,用于添加到 MP4 文件:

3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 3F 3E 3C 72 64 66 3A 53 70 68 65 72 69 63 61 6C 56 69 64 65 6F 0A 78 6D 6C 6E 73 3A 72 64 66 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 31 39 39 39 2F 30 32 2F 32 32 2D 72 64 66 2D 73 79 6E 74 61 78 2D 6E 73 23 22 0A 78 6D 6C 6E 73 3A 47 53 70 68 65 72 69 63 61 6C 3D 22 68 74 74 70 3A 2F 2F 6E 73 2E 67 6F 6F 67 6C 65 2E 63 6F 6D 2F 76 69 64 65 6F 73 2F 31 2E 30 2F 73 70 68 65 72 69 63 61 6C 2F 22 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 70 68 65 72 69 63 61 6C 3E 74 72 75 65 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 70 68 65 72 69 63 61 6C 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 65 64 3E 74 72 75 65 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 65 64 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 69 6E 67 53 6F 66 74 77 61 72 65 3E 53 70 68 65 72 69 63 61 6C 20 4D 65 74 61 64 61 74 61 20 54 6F 6F 6C 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 53 74 69 74 63 68 69 6E 67 53 6F 66 74 77 61 72 65 3E 3C 47 53 70 68 65 72 69 63 61 6C 3A 50 72 6F 6A 65 63 74 69 6F 6E 54 79 70 65 3E 65 71 75 69 72 65 63 74 61 6E 67 75 6C 61 72 3C 2F 47 53 70 68 65 72 69 63 61 6C 3A 50 72 6F 6A 65 63 74 69 6F 6E 54 79 70 65 3E 3C 2F 72 64 66 3A 53 70 68 65 72 69 63 61 6C 56 69 64 65 6F 3E
Run Code Online (Sandbox Code Playgroud)

注意:和.之间的不是句号 (byte: ),而是换行标记 (byte: )。如果您只是复制/粘贴 XML 文本本身,那么您可能会丢失一些不显示为文本的字节(变成句号或空格,具体取决于您的文本查看器)。SphericalVideoxmlns2E0A

2)添加元数据。

(a)TRAK通过在框末尾添加 454 个元数据字节进行更新trak

要找到它,trak请查找 bytes74 72 61 6B并将位置记为 integer atom_start。前 4 个字节保存该原子的大小。因此,去定位atom_start minus 4并做readInt会给你带来atom_size

(b) 从atom_start minus 4现在的位置向前跳转atom_size,然后在那里插入元数据字节。

3)更新尺寸和偏移量。

(a) 更新 TRAK 大小:
返回到位置atom_start minus 4,现在用 的逻辑覆盖当前大小,new_Size = current_Size + 454;以考虑这些新添加的字节。

(b) 更新 MOOV 大小:
找到这moov是 bytes 6D 6F 6F 76。前 4 个字节是大小整数,您可以通过添加来覆盖当前大小+454以适应大小的增加。

(c) 更新 STCO 偏移量:
查找stco哪个是 bytes 73 74 63 6F。跳过这 4 个字节并跳过另外 4 个字节(通常列为00 00 00 00)。现在,接下来的 4 个字节告诉您列出了多少个偏移量条目,使用该数字可以知道何时停止更新以下整数值。您可以使用 For 循环进行更新。

原子的例子STCO

73 74 63 6F 00 00 00 00 00 00 00 02 00 00 04 E5 00 00 07 BB
Run Code Online (Sandbox Code Playgroud)

意义...

73 74 63 6F: 使文本成为stco文本。
00 00 00 00:跳过这些字节。
00 00 00 02:表示有 2 个偏移量条目。
00 00 04 E5:条目 1 = 1253(因此在此值上添加 +454)。
00 00 07 BB:条目 2 = 1979(因此在此值上添加 +454)。

结构STCO

内部字节偏移量的结构STCO