字幕
更新时间:2020-12-11
创建字幕轨道
- 创建字幕轨道,使用字幕相关功能,需要创建字幕轨并添加到媒体轨道中心,并创建一个字幕片段,配合字幕UI逻辑使用,详见智能小视频源码,涉及组件BDHKVlogSubtitlesView(字幕位置),BDMVSubtitleInputAccessoryView(字幕输入框),BDMVInputEventBottomBar(字幕确认框)
- 代码示例如下:
//创建字幕轨道
RMVPMediaVideoBlendItem *blendItem1 = [[RMVPMediaVideoBlendItem alloc] initWithBlendMode:RMVPMediaVideoBlendModeNormal];
subtitleTrack = [[RMVPMediaVisibleTrack alloc] initWithBlendItem:blendItem1];
subtitleTrack.trackId = kBDMVMediaVisibleSubtitleTrackId;
[self.videoTrack addVideoTrack:subtitleTrack];
//添加字幕片段
RMVPMediaTextSegment *subtitleSegment = [[RMVPMediaTextSegment alloc] init];
[subtitleTrack addSegment: subtitleSegment];
//配置字幕与预览实时显示
CGFloat videoWidth = self.previewer.previewConfig.width;
CGFloat videoHeight = self.previewer.previewConfig.height;
[self.videoTrack setupSubtitleStyleWithPreviewSize:CGSizeMake(videoWidth, videoHeight)];
添加多段字幕
- 添加多段字幕,请参考智能小视频编辑预览BBAShortVideoPreviewViewController.mm文件中的字幕逻辑,字幕默认显示2S
- 代码示例如下:
//获取字幕轨道中字幕片段
RMVPMediaTextSegment *textSegment = [self.videoTrack subtitleSegment];
//设置字幕内容,获取媒体轨道中心当前时间
CMTime currentTime = self.previewer.cursor.cursorTime;
//新增字幕
if (!currentItem) {
currentItem = [[RMVPMediaTextItem alloc] init];
currentItem.mainText = self.tmpMainTitle;
currentItem.subText = self.tmpSubTitle;
RMVPMediaTextItem *nextTextItem = nil;
NSArray *textAllItems = [textSegment textAllItem];
for (RMVPMediaTextItem *tmpItem in textAllItems) {
CMTimeRange timeRange = tmpItem.timeRange;
if (CMTimeCompare(timeRange.start, currentTime) > 0) {
nextTextItem = tmpItem;
break;
}
}
CGFloat newSubtitleDuration = [BDMVEditSubtitleSettings sharedInstance].addSubtitleDuration;
if (newSubtitleDuration <= 0) newSubtitleDuration = 2;
if (nextTextItem) {
CMTime eventualDuration;
CMTime nextItemStartTime = nextTextItem.timeRange.start;
CMTime gapTime = CMTimeSubtract(nextItemStartTime, currentTime);
if (CMTimeCompare(gapTime, CMTimeMake(newSubtitleDuration, 1)) >= 0) {
eventualDuration = CMTimeMake(newSubtitleDuration, 1);
} else {
eventualDuration = gapTime;
}
currentItem.timeRange = CMTimeRangeMake(currentTime, eventualDuration);
NSInteger index = [textSegment textIndexAtRefTime:nextItemStartTime];
//插入字幕到指定位置
[textSegment insertTextAtIndex:index item:currentItem];
[self.subtitleEditManager.seekBarAera insertSubtitleAtIndex:index];
} else {
CMTime eventualDuration;
CMTime mediaDuration = self.tracksCenter.userTrack.trackDuration;
CMTime remainingDuration = CMTimeSubtract(mediaDuration, currentTime);
if (CMTimeCompare(remainingDuration, CMTimeMake(newSubtitleDuration, 1)) >= 0) {
eventualDuration = CMTimeMake(newSubtitleDuration, 1);
} else {
eventualDuration = remainingDuration;
}
currentItem.timeRange = CMTimeRangeMake(currentTime, eventualDuration);
//追加字幕
[textSegment addTextWithItem:currentItem];
[self.subtitleEditManager.seekBarAera addSubtitle];
}
NSInteger index = [textSegment textIndexAtRefTime:self.previewer.cursor.cursorTime];
//更新字幕显示位置,详见[3.3.4 设置字幕画面位置]
[self updateSubtitleDisplayAndRealSubtitlePositonWithTransition:SubtitleInitTranslation itemIndex:index];
} else { // 编辑字幕
currentItem.mainText = self.tmpMainTitle;
currentItem.subText = self.tmpSubTitle;
NSInteger index = [textSegment textIndexAtRefTime:currentTime];
[self.subtitleEditManager.seekBarAera editSubtitleAtIndex:index];
}
设置字幕画面位置
- 设置字幕画面位置,可以调整字幕轨道上某个字幕的显示位置
- 代码示例如下:
//设置字幕显示位置
currentFrame = self.displaySubtitleTextView.frame;//displayView的位置已经更新
CGSize scale = [self currentVideoScale];
BDMVPreviewTransform transform = self.subtitlePreviewTransform;
CGFloat left = (CGRectGetMinX(currentFrame) - CGRectGetMinX(availabelRect) + Subtitle_InputView_OffsetX) / transform.scale;
left += [self currentVideoInvisibleHorizontalPadding];
CGFloat bottom = (CGRectGetMaxY(availabelRect) - CGRectGetMaxY(currentFrame) + Subtitle_InputView_OffsetX) / transform.scale;
CGFloat right = (CGRectGetMaxX(availabelRect) - CGRectGetMaxX(currentFrame) + Subtitle_InputView_OffsetX) / transform.scale;
right += [self currentVideoInvisibleHorizontalPadding];
RMVPMediaTextSegment *currentSegment = [self.tracksCenter subtitleSegment];
NSDictionary *attributes = @{@"marginBottom":@(bottom * scale.height),
@"marginLeft":@(left * scale.width),
@"marginRight":@(right * scale.width)};
[currentSegment updateStyleAtIndex:index styleAttributes:attributes];