使用 AVFoundation 创建视频时添加章节轨道

问题描述 投票:0回答:2

我正在从一堆静态图像创建视频(QuickTime .mov 格式,H.264 编码),并且我想在此过程中添加章节轨道。 视频创建得很好,我没有检测到任何错误,但 QuickTime Player 不显示任何章节。 我知道这个问题,但它并不能解决我的问题。

旧版 QuickTime Player 7 与最新版本不同,可以显示有关电影曲目的信息。 当我打开带有工作章节的电影(使用旧的 QuickTime 代码创建)时,我会看到一个视频轨道和一个文本轨道,并且视频轨道知道文本轨道正在为视频提供章节。 然而,如果我检查由我的新代码创建的电影,会发现视频轨道和元数据轨道一起存在,但 QuickTime 不知道元数据轨道应该提供章节。 我读过的东西让我相信应该在章节中使用元数据,但有人真正做到这一点吗? 文本轨道有用吗?

这是我为元数据创建

AVAssetWriterInput
的方法。

// Make dummy AVMetadataItem to get its format
AVMutableMetadataItem* dummyMetaItem = [AVMutableMetadataItem metadataItem];
dummyMetaItem.identifier = AVMetadataIdentifierQuickTimeUserDataChapter;
dummyMetaItem.dataType = (NSString*) kCMMetadataBaseDataType_UTF8;
dummyMetaItem.value = @"foo";
AVTimedMetadataGroup* dummyGroup = [[[AVTimedMetadataGroup alloc]
    initWithItems: @[dummyMetaItem]
    timeRange: CMTimeRangeMake( kCMTimeZero, kCMTimeInvalid )] autorelease];
CMMetadataFormatDescriptionRef metaFmt = [dummyGroup copyFormatDescription];

// Make the input
AVAssetWriterInput* metaWriterInput = [AVAssetWriterInput
    assetWriterInputWithMediaType: AVMediaTypeMetadata
    outputSettings: nil
    sourceFormatHint: metaFmt];
CFRelease( metaFmt );

// Associate metadata input with video input
[videoInput addTrackAssociationWithTrackOfInput: metaWriterInput
    type: AVTrackAssociationTypeChapterList];

// Associate metadata input with AVAssetWriter
[writer addInput: metaWriterInput];

// Create a metadata adaptor
AVAssetWriterInputMetadataAdaptor* metaAdaptor = [AVAssetWriterInputMetadataAdaptor
    assetWriterInputMetadataAdaptorWithAssetWriterInput: metaWriterInput];

附注我尝试使用文本轨道(

AVAssetWriterInput
,类型为
AVMediaTypeText
),QuickTime Player 表示结果“不是电影”。不知道我做错了什么。

macos video avfoundation metadata
2个回答
1
投票

我设法使用文本轨道来提供章节。 我经历了一次苹果开发者技术支持事件,并被告知这是正确的做法。

设置:

我假设

AVAssetWriter
已创建,并且已为其分配了视频轨道的
AVAssetWriterInput

这里最棘手的部分是创建文本格式描述。 文档说

CMTextFormatDescriptionCreateFromBigEndianTextDescriptionData
TextDescription
结构作为输入,但忽略了该结构的定义位置。 它位于 Movies.h 中,而 Movies.h 位于 QuickTime.framework 中,而 QuickTime.framework 不再是 Mac OS SDK 的一部分。 谢谢,苹果。

// Create AVAssetWriterInput
AVAssetWriterInput* textWriterInput = [AVAssetWriterInput
    assetWriterInputWithMediaType: AVMediaTypeText
    outputSettings: nil ];
textWriterInput.marksOutputTrackAsEnabled = NO;

// Connect input to writer
[writer addInput: textWriterInput];

// Mark the text track as providing chapter for the video
[videoWriterInput addTrackAssociationWithTrackOfInput: textWriterInput
    type: AVTrackAssociationTypeChapterList];

// Create the text format description, which we will need
// when creating each sample.
CMFormatDescriptionRef textFmt = NULL;
TextDescription textDesc;
memset( &textDesc, 0, sizeof(textDesc) );
textDesc.descSize = OSSwapHostToBigInt32( sizeof(textDesc) );
textDesc.dataFormat = OSSwapHostToBigInt32( 'text' );
CMTextFormatDescriptionCreateFromBigEndianTextDescriptionData( NULL,
    (const uint8_t*)&textDesc, sizeof(textDesc), NULL, kCMMediaType_Text,
    &textFmt );

编写示例:

CMSampleTimingInfo timing =
{
    CMTimeMakeWithSeconds( endTime - startTime, timeScale ),    // duration
    CMTimeMakeWithSeconds( startTime, timeScale ),
    kCMTimeInvalid
};
CMSampleBufferRef textSample = NULL;
CMPSampleBufferCreateWithText( NULL, (CFStringRef)theTitle, true, NULL, NULL,
    textFmt, &timing, &textSample );
[textWriterInput appendSampleBuffer: textSample];

函数

CMPSampleBufferCreateWithText
取自开源CoreMediaPlus


0
投票

如果您不想使用 CMPSampleBufferCreateWithText,您可以自行推出类似于 https://yhf8377.medium.com/quicktime-movie-editing-using-avfoundation-and-swift-5-33965c522abc (代码流程为任何语言都基本相同)

但我写在这里的真正原因是参考这个 How to create a CMBlockBufferRef from NSData

数据所有权并不十分明显,因为稍后可能会在另一个作用域中写入相同的 buf。因此,如果您构建了一个 NSData,它可能会在写入示例缓冲区之前被释放,这最终会导致一个没有标题的章节。在这方面花了很长时间,但您需要传递所有权,因为数据是引用的而不是复制的。

© www.soinside.com 2019 - 2024. All rights reserved.