GPUImage官方的示例工程里有個SimpleVideoFilter,實時攝像頭內容加上濾鏡。然而這個工程寫得非常簡單,錄像是自動啟動的,錄制10秒停止。
研究一下代碼,發現錄制代碼在-(void)viewDidLoad最后部分,2個dispatch_after調用。第一個dispatch_after開始錄制,然后里面一層的dispatch_after停止錄制并保存到手機相冊。明確了功能就可以把這2部分代碼拿出來,放在一個button事件中。
然而,問題隨之出現,按下start錄制,stop停止。按鈕又變成start,此時再按下去,會報錯,status is 3(也有可能是2,數字是幾不重要)。
查閱官方文檔,了解一下status含義。
enum {
AVAssetWriterStatusUnknown = 0,
AVAssetWriterStatusWriting,
AVAssetWriterStatusCompleted,
AVAssetWriterStatusFailed,
AVAssetWriterStatusCancelled
};
3是completed,就是說,AssetWriter這個實例已經完成了一次攝像頭寫入文件的動作,狀態已經完成,不能再次開始寫入。
報錯是在[movieWriter startRecording];這行出現,追溯源碼,可以看到GPUImageMovieWriter其實是對AssetWriter進行了一次封裝,其核心的寫文件的動作還是由AssetWriter完成。這個錯誤信息就是從AssetWriter發出的。
查看源碼可以發現[movieWriter finishRecording];以后并沒有新建一個AssetWriter實例。那么我們盡量不改動GPUImage源碼,在使用上對自己的app邏輯進行改進。
示例代碼使用ALAssetsLibrary,調用[library writeVideoAtPathToSavedPhotosAlbum:completionBlock:]來寫入相冊,在completionBlock中我們可以在最后加入幾行代碼
[_videoCamera removeTarget:_movieWriter];//1
[[NSFileManager defaultManager] removeItemAtURL:_movieURL error:nil];//2
[self initMovieWriter];//3
[_videoCamera addTarget:_movieWriter];//4
- (void)initMovieWriter {
_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:_movieURL size:CGSizeMake(720.0, 1280.0)];
_movieWriter.encodingLiveVideo = YES;
}
- (void)initMovieWriter是我自己提取出來的。封裝一下初始化方法。
1.攝像頭實例取消對GPUImageMovieWriter的綁定,因為重新實例化新的GPUImageMovieWriter以后原來的實例就沒用了。
2.刪除原來已經寫好的影片文件,如果新的實例直接寫入已存在的文件會報錯AVAssetWriterStatusFailed。
3.重新實例化一個GPUImageMovieWriter。
4.把新的GPUImageMovieWriter綁定到攝像頭實例。
這樣我們就可以不停的攝像,保存,再攝像,再保存,再也不報錯了。