将 360° 元数据插入 java 中的 mp4 文件
Insert 360° metadata to mp4 file in java
我正在尝试使用此库将 360° 元数据添加到 mp4 文件:https://github.com/copiousfreetime/mp4parser
检查代码后,我创建了这个:
public void injectSphericalMetaV2(TrackBox trackBox) throws IOException {
String sphericalVideoGlobalMetadata = "<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>GIROPTIC 360 CAM</GSpherical:StitchingSoftware><GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType></rdf:SphericalVideo>";
String UUID_ID = "FFCC8263-F855-4A93-8814-587A02521FDD";
UserBox sphericalAtom = new UserBox(UUID_ID.getBytes());
sphericalAtom.setData(sphericalVideoGlobalMetadata.getBytes());
trackBox.addBox(sphericalAtom);
}
我在这里执行它:
protected TrackBox createTrackBox(Track track, Movie movie, Map<Track, int[]> chunks) {
TrackBox trackBox = new TrackBox();
TrackHeaderBox tkhd = new TrackHeaderBox();
tkhd.setEnabled(true);
tkhd.setInMovie(true);
tkhd.setMatrix(track.getTrackMetaData().getMatrix());
tkhd.setAlternateGroup(track.getTrackMetaData().getGroup());
tkhd.setCreationTime(track.getTrackMetaData().getCreationTime());
if (track.getEdits() == null || track.getEdits().isEmpty()) {
tkhd.setDuration(track.getDuration() * getTimescale(movie) / track.getTrackMetaData().getTimescale());
} else {
long d = 0;
for (Edit edit : track.getEdits()) {
d += (long) edit.getSegmentDuration();
}
tkhd.setDuration(d * track.getTrackMetaData().getTimescale());
}
tkhd.setHeight(track.getTrackMetaData().getHeight());
tkhd.setWidth(track.getTrackMetaData().getWidth());
tkhd.setLayer(track.getTrackMetaData().getLayer());
tkhd.setModificationTime(new Date());
tkhd.setTrackId(track.getTrackMetaData().getTrackId());
tkhd.setVolume(track.getTrackMetaData().getVolume());
trackBox.addBox(tkhd);
trackBox.addBox(createEdts(track, movie));
MediaBox mdia = new MediaBox();
trackBox.addBox(mdia);
MediaHeaderBox mdhd = new MediaHeaderBox();
mdhd.setCreationTime(track.getTrackMetaData().getCreationTime());
mdhd.setDuration(track.getDuration());
mdhd.setTimescale(track.getTrackMetaData().getTimescale());
mdhd.setLanguage(track.getTrackMetaData().getLanguage());
mdia.addBox(mdhd);
HandlerBox hdlr = new HandlerBox();
mdia.addBox(hdlr);
hdlr.setHandlerType(track.getHandler());
MediaInformationBox minf = new MediaInformationBox();
if (track.getHandler().equals("vide")) {
try {
injectSphericalMetaV2(trackBox);
} catch (IOException e) {
e.printStackTrace();
}
minf.addBox(new VideoMediaHeaderBox());
} else if (track.getHandler().equals("soun")) {
minf.addBox(new SoundMediaHeaderBox());
} else if (track.getHandler().equals("text")) {
minf.addBox(new NullMediaHeaderBox());
} else if (track.getHandler().equals("subt")) {
minf.addBox(new SubtitleMediaHeaderBox());
} else if (track.getHandler().equals("hint")) {
minf.addBox(new HintMediaHeaderBox());
} else if (track.getHandler().equals("sbtl")) {
minf.addBox(new NullMediaHeaderBox());
}
// dinf: all these three boxes tell us is that the actual
// data is in the current file and not somewhere external
DataInformationBox dinf = new DataInformationBox();
DataReferenceBox dref = new DataReferenceBox();
dinf.addBox(dref);
DataEntryUrlBox url = new DataEntryUrlBox();
url.setFlags(1);
dref.addBox(url);
minf.addBox(dinf);
Box stbl = createStbl(track, movie, chunks);
minf.addBox(stbl);
mdia.addBox(minf);
LOG.logDebug("done with trak for track_" + track.getTrackMetaData().getTrackId());
return trackBox;
}
这 2 个方法在我的 MP4BuilderV2 中,我在这里将其称为 TrimActivity,如下所示:
Container out = new DefaultMp4BuilderV2().build(movie);
MovieHeaderBox mvhd = Path.getPath(out, "moov/mvhd");
mvhd.setMatrix(Matrix.ROTATE_180);
if (!dst.exists()) {
dst.createNewFile();
} else {
dst.delete();
dst.createNewFile();
}
FileOutputStream fos = new FileOutputStream(dst);
WritableByteChannel fc = fos.getChannel();
try {
out.writeContainer(fc);
}catch (Exception e) {
Log.e("erreur", e.toString());
}finally {
fc.close();
fos.close();
file.close();
}
file.close();
但在最后 try/catch 我得到这个错误:java.nio.BufferOverflowException
如果有人有解决方案提前致谢
我遇到了和你一样的问题,在寻找解决方案时我找到了一个 meta tag insertion implementation 适合我的方法,也许它对你有帮助。
我正在尝试使用此库将 360° 元数据添加到 mp4 文件:https://github.com/copiousfreetime/mp4parser
检查代码后,我创建了这个:
public void injectSphericalMetaV2(TrackBox trackBox) throws IOException {
String sphericalVideoGlobalMetadata = "<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>GIROPTIC 360 CAM</GSpherical:StitchingSoftware><GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType></rdf:SphericalVideo>";
String UUID_ID = "FFCC8263-F855-4A93-8814-587A02521FDD";
UserBox sphericalAtom = new UserBox(UUID_ID.getBytes());
sphericalAtom.setData(sphericalVideoGlobalMetadata.getBytes());
trackBox.addBox(sphericalAtom);
}
我在这里执行它:
protected TrackBox createTrackBox(Track track, Movie movie, Map<Track, int[]> chunks) {
TrackBox trackBox = new TrackBox();
TrackHeaderBox tkhd = new TrackHeaderBox();
tkhd.setEnabled(true);
tkhd.setInMovie(true);
tkhd.setMatrix(track.getTrackMetaData().getMatrix());
tkhd.setAlternateGroup(track.getTrackMetaData().getGroup());
tkhd.setCreationTime(track.getTrackMetaData().getCreationTime());
if (track.getEdits() == null || track.getEdits().isEmpty()) {
tkhd.setDuration(track.getDuration() * getTimescale(movie) / track.getTrackMetaData().getTimescale());
} else {
long d = 0;
for (Edit edit : track.getEdits()) {
d += (long) edit.getSegmentDuration();
}
tkhd.setDuration(d * track.getTrackMetaData().getTimescale());
}
tkhd.setHeight(track.getTrackMetaData().getHeight());
tkhd.setWidth(track.getTrackMetaData().getWidth());
tkhd.setLayer(track.getTrackMetaData().getLayer());
tkhd.setModificationTime(new Date());
tkhd.setTrackId(track.getTrackMetaData().getTrackId());
tkhd.setVolume(track.getTrackMetaData().getVolume());
trackBox.addBox(tkhd);
trackBox.addBox(createEdts(track, movie));
MediaBox mdia = new MediaBox();
trackBox.addBox(mdia);
MediaHeaderBox mdhd = new MediaHeaderBox();
mdhd.setCreationTime(track.getTrackMetaData().getCreationTime());
mdhd.setDuration(track.getDuration());
mdhd.setTimescale(track.getTrackMetaData().getTimescale());
mdhd.setLanguage(track.getTrackMetaData().getLanguage());
mdia.addBox(mdhd);
HandlerBox hdlr = new HandlerBox();
mdia.addBox(hdlr);
hdlr.setHandlerType(track.getHandler());
MediaInformationBox minf = new MediaInformationBox();
if (track.getHandler().equals("vide")) {
try {
injectSphericalMetaV2(trackBox);
} catch (IOException e) {
e.printStackTrace();
}
minf.addBox(new VideoMediaHeaderBox());
} else if (track.getHandler().equals("soun")) {
minf.addBox(new SoundMediaHeaderBox());
} else if (track.getHandler().equals("text")) {
minf.addBox(new NullMediaHeaderBox());
} else if (track.getHandler().equals("subt")) {
minf.addBox(new SubtitleMediaHeaderBox());
} else if (track.getHandler().equals("hint")) {
minf.addBox(new HintMediaHeaderBox());
} else if (track.getHandler().equals("sbtl")) {
minf.addBox(new NullMediaHeaderBox());
}
// dinf: all these three boxes tell us is that the actual
// data is in the current file and not somewhere external
DataInformationBox dinf = new DataInformationBox();
DataReferenceBox dref = new DataReferenceBox();
dinf.addBox(dref);
DataEntryUrlBox url = new DataEntryUrlBox();
url.setFlags(1);
dref.addBox(url);
minf.addBox(dinf);
Box stbl = createStbl(track, movie, chunks);
minf.addBox(stbl);
mdia.addBox(minf);
LOG.logDebug("done with trak for track_" + track.getTrackMetaData().getTrackId());
return trackBox;
}
这 2 个方法在我的 MP4BuilderV2 中,我在这里将其称为 TrimActivity,如下所示:
Container out = new DefaultMp4BuilderV2().build(movie);
MovieHeaderBox mvhd = Path.getPath(out, "moov/mvhd");
mvhd.setMatrix(Matrix.ROTATE_180);
if (!dst.exists()) {
dst.createNewFile();
} else {
dst.delete();
dst.createNewFile();
}
FileOutputStream fos = new FileOutputStream(dst);
WritableByteChannel fc = fos.getChannel();
try {
out.writeContainer(fc);
}catch (Exception e) {
Log.e("erreur", e.toString());
}finally {
fc.close();
fos.close();
file.close();
}
file.close();
但在最后 try/catch 我得到这个错误:java.nio.BufferOverflowException
如果有人有解决方案提前致谢
我遇到了和你一样的问题,在寻找解决方案时我找到了一个 meta tag insertion implementation 适合我的方法,也许它对你有帮助。