基于Bento4库,对MP4的视频注入360元素,使得MP4的视频,变成360全景视频。
Bento4官网地址:https://www.bento4.com
Bento4的git地址:https://github.com/axiomatic-systems/Bento4
clone 代码后,可在项目中,查看Readme文档,可以使用cmake 指令操作,也可以用mac xcode的。
因为有Xcode,所以我这里,直接用xcode的编译
目录:Bento4-master/Build/Targets/universal-apple-macosx/Bento4.xcodeproj ,
点击打开Bento4.xcodeproj
Scheme,选择Bento4,然后在Build Phases的Headers中,把Project的头文件,放到Public,最后编译,获得lib + include。
把CApi 和Runtime 中需要的文件,拖拽进来。
然后新建一个NSObject类型MaBento4Tool,把.m 改成 .mm 变成C++的类
在.h 定义函数:
+ (BOOL)inject360MetadataFromInputMP4:(NSString *)inputPath
outputMP4:(NSString*)outputPath;
在.mm 中实现:
#import"Ap4.h"
#import "Ap4UuidAtom.h"
#include "Ap4FileByteStream.h"
+ (BOOL)inject360MetadataFromInputMP4:(NSString *)inputPath{
outputMP4:(NSString*)outputPath{
// ---------- 1. 加载 JSON 数据 ----------
NSDictionary*sphericalMeta =@{
@"Spherical":@YES,
@"Stitched":@YES,
@"StereoMode":@"mono",
@"projection": @"equirectangular",
@"SourceCount": @(1),
@"side_data_type": @"Spherical Mappin",
@"initial_view_orientation": @{
@"yaw":@0,
@"pitch":@0,
@"roll":@0
}
};
NSDictionary*dict =@{@"side_data_list":sphericalMeta};
NSError*error =nil;
NSData*jsonData = [NSJSONSerializationdataWithJSONObject:dictoptions:0error:&error];
if(!jsonData || error) {
NSLog(@"❌ JSON 构建失败: %@", error);
returnNO;
}
// ---------- 2. 创建读写 ByteStream ----------
AP4_ByteStream* input =nullptr;
AP4_ByteStream* output =nullptr;
// 打开输入 MP4(用于读)
AP4_Resultresult =AP4_FileByteStream::Create([inputPathUTF8String],AP4_FileByteStream::STREAM_MODE_READ, input);
if(AP4_FAILED(result) || !input) {
NSLog(@"❌ 无法打开输入 MP4");
returnNO;
}
// 打开输出 MP4(用于写)
result =AP4_FileByteStream::Create([outputPathUTF8String],AP4_FileByteStream::STREAM_MODE_WRITE, output);
if(AP4_FAILED(result) || !output) {
input->Release();
NSLog(@"❌ 无法打开输出 MP4");
returnNO;
}
// ---------- 3. 加载 MP4 文件结构 ----------
AP4_Filemp4File(*input);
AP4_Movie* movie = mp4File.GetMovie();
if(!movie) {
NSLog(@"❌ 无法读取 MP4 movie 对象");
input->Release();
output->Release();
returnNO;
}
// ---------- 4. 注入 JSON(Google Spherical Video V2)到 sample description ----------
AP4_List::Item* trackItem = movie->GetTracks().FirstItem();
while(trackItem) {
AP4_Track* track = trackItem->GetData();
if(track && track->GetType() ==AP4_Track::TYPE_VIDEO) {
if(track) {
constAP4_UI08v1_uuid[] = {
0xFF,0xCC,0x82,0x63,
0xF8,0x55,
0x4A,0x93,
0x88,0x14,
0x58,0x7A,0x02,0x52,0x1F,0xDD
};
constchar* sphericalXml =
""
"
" xmlns:GSpherical=\"http://ns.google.com/videos/1.0/spherical/\">"
"true"
"true"
"mono"
"Spherical Metadata Tool"
"equirectangular"
"";
AP4_DataBufferuuidPayload((constAP4_Byte*)sphericalXml, (AP4_Size)strlen(sphericalXml));
// 创建内存字节流
AP4_MemoryByteStream* memStream = new AP4_MemoryByteStream(
(constAP4_UI08*)sphericalXml,
(AP4_Size)strlen(sphericalXml)
);
// 创建 UUID box
AP4_UnknownUuidAtom* uuidAtom = new AP4_UnknownUuidAtom(
(AP4_UI64)strlen(sphericalXml),
v1_uuid,
*memStream
);
constAP4_Atom* trakAtomConst = track->GetTrakAtom();
AP4_ContainerAtom* trakAtom =dynamic_cast((AP4_Atom*)trakAtomConst);
if(trakAtom) {
trakAtom->AddChild(uuidAtom);
NSLog(@"✅ 注入 Google Spherical V1 (XML)");
}else{
NSLog(@"❌ trakAtom 无法转换为 Container 类型");
}
break;
}
}
trackItem = trackItem->GetNext();
}
// ---------- 6. 保存文件 ----------
AP4_FileWriter::Write(mp4File, *output);
input->Release();
output->Release();
NSLog(@"✅ 360 Metadata 注入成功!");
return YES;
}
然后在项目中,就可以开心调用;
[MaBento4Tool inject360MetadataFromInputMP4:“输入的视频地址” outputMP4:"输出的视频地址"];
查看视频信息指令:(需要在终端中安装ffmpeg,后再执行)
ffprobe -v quiet -print_format json -show_format -show_streams “视频地址”
如果有看到如下信息, 恭喜你,你已经成功注入360全景视频元素
"side_data_list": [
{
"side_data_type": "Spherical Mapping",
"projection": "equirectangular",
"yaw": 0,
"pitch": 0,
"roll": 0
}
]
之前踩过的坑
1)通过生成一秒的360模版视频A,然后通过ffmpeg,把视频A的元素取出赋值到 视频B中,通过查看视频信息,未查找相关信息
2)GPAC的库,通过相关编译,集成后,还是各种报错
如果有时间,你们也可以尝试以上两点,是否能走通,麻烦告知。