一:问题描述
拍摄暂停有时产生的视频文件第一帧或者最后一帧视频黑屏。
二:问题的原因
视频第一帧黑屏的原因:采集的时候音频在视频前面采集导致的问题。
第一种解决办法的可以参考的链接:解决第一帧视频问题的链接
视频最后一帧黑屏的原因:在音频帧的结束因为比视频帧长。
三:视频最后一帧黑屏解决方法
1:在调用GPUImageMovieWriter界面里面执行movieWriter finishRecording的回调移除
[movieWriter finishRecordingWithCompletionHandler:^{
[filter removeTarget:movieWriter];
self.videoCamera.audioEncodingTarget=nil;
movieWriter=nil;
}];
2:GPUImage库里面GPUImageMovieWriter需要更改的问题(+是添加代码 -是删除代码)
@@ -28,6 +28,9 @@ @interface GPUImageMovieWriter ()
GPUImageFramebuffer *firstInputFramebuffer;
BOOL discont;
+ BOOL allowWriteAudio;
+ BOOL willFinish;
+ void (^completeHandler)(void);
CMTime startTime, previousFrameTime, previousAudioTime;
CMTime offsetTime;
@@ -278,6 +281,7 @@ - (void)startRecording;
}
});
isRecording = YES;
+ allowWriteAudio = NO;
// [assetWriter startSessionAtSourceTime:kCMTimeZero];
}
@@ -321,14 +325,24 @@ - (void)finishRecording;
- (void)finishRecordingWithCompletionHandler:(void (^)(void))handler;
{
runSynchronouslyOnContextQueue(_movieWriterContext, ^{
- isRecording = NO;
-
+ willFinish = NO;
if (assetWriter.status == AVAssetWriterStatusCompleted || assetWriter.status == AVAssetWriterStatusCancelled || assetWriter.status == AVAssetWriterStatusUnknown)
{
+ isRecording = NO;
if (handler)
runAsynchronouslyOnContextQueue(_movieWriterContext, handler);
return;
}
+ allowWriteAudio = NO;
+ if (CMTimeCompare(previousFrameTime, previousAudioTime) == -1) {
+ // recoreded audio frame is longer than video frame
+ willFinish = YES;
+ completeHandler = handler;
+ return;
+ }
+ completeHandler = NULL;
+ isRecording = NO;
+
if( assetWriter.status == AVAssetWriterStatusWriting && ! videoEncodingIsFinished )
{
videoEncodingIsFinished = YES;
@@ -365,7 +379,7 @@ - (void)finishRecordingWithCompletionHandler:(void (^)(void))handler;
- (void)processAudioBuffer:(CMSampleBufferRef)audioBuffer;
{
- if (!isRecording || _paused)
+ if (!isRecording || _paused || !allowWriteAudio)
{
return;
}
@@ -744,6 +758,7 @@ - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
[assetWriter startSessionAtSourceTime:frameTime];
startTime = frameTime;
+ allowWriteAudio = YES;
});
}
@@ -819,6 +834,11 @@ - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
write();
[inputFramebufferForBlock unlock];
+
+ if (willFinish && CMTimeCompare(previousFrameTime, previousAudioTime) != -1) {
+ willFinish = NO;
+ [self finishRecordingWithCompletionHandler:completeHandler];
+ }
});
}
四:特别提醒当加入音乐和滤镜等编辑视频的时候音频和视频对不上问题(是由上面的问题导致的,在这里我们可以只在拍摄生成视频是设置一个变量来限制是否更改GPUImageMovieWriter的添加就好)
如果不太明白代码里有怎么添加的详细解释请看链接:这里有我怎么设置变量的说明
五总结:
解决这些问题查看了不少底层库代码的实现方法,翻阅了一些英文版的问题log,查看了不少GPUImage导致的问题说明,总的来说,虽然解决问题的过程比较痛苦,但是收获了不少底层库函数的方法运用,记录下来这些问题和解决办法以供需要的人参考,如果有更好的解决办法,大家可以指点和留言