播放电影停止 avcapturesession 录制
Posted
技术标签:
【中文标题】播放电影停止 avcapturesession 录制【英文标题】:playing a movie stops avcapturesession recording 【发布时间】:2012-09-20 10:08:47 【问题描述】:我有一个 ios 应用,可以在后台录制前置摄像头的视频,并且运行良好。但现在我正在尝试同时播放一个简短的 mp4,并且使用 MPMoviePlayerController 播放会停止捕获会话。
我尝试了 AVPlayer,但结果相同。 我还设置了 [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; 仍然没有运气。有没有人遇到并解决了同样的问题。 感谢您的任何建议。
使用 ios5 SDK。
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *recButton=[[UIButton alloc] initWithFrame:CGRectMake(10,200, 200,40)] ;
recButton.backgroundColor = [UIColor blackColor];
[recButton addTarget:self action:@selector(startRecording) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:recButton];
isRecording=NO;
- (void)viewDidUnload
[super viewDidUnload];
// Release any retained subviews of the main view.
-(void) viewWillAppear:(BOOL)animated
self.navigationController.navigationBarHidden = YES;
-(void) viewWillDisappear:(BOOL)animated
self.navigationController.navigationBarHidden = NO;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
return (interfaceOrientation == UIInterfaceOrientationPortrait);
else
return YES;
#pragma mark video playing
-(void) startRecording
if (isRecording)
[self stopVideoRecording];
isRecording=NO;
else
[self initCaptureSession];
[self startVideoRecording];
isRecording=YES;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:@"new"
ofType:@"mov"]];
[self playMovieAtURL:url];
-(void) playMovieAtURL: (NSURL*) theURL
player =
[[MPMoviePlayerController alloc] initWithContentURL: theURL ];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
player.scalingMode = MPMovieScalingModeAspectFill;
player.controlStyle = MPMovieControlStyleNone;
[player prepareToPlay];
// Register for the playback finished notification
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(myMovieFinishedCallback:)
name: MPMoviePlayerPlaybackDidFinishNotification
object: player];
[player.view setFrame: self.view.bounds];
[self.view addSubview:player.view];
// Movie playback is asynchronous, so this method returns immediately.
[player play];
// When the movie is done, release the controller.
-(void) myMovieFinishedCallback: (NSNotification*) aNotification
MPMoviePlayerController* theMovie = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver: self
name: MPMoviePlayerPlaybackDidFinishNotification
object: theMovie];
[player.view removeFromSuperview];
[self stopVideoRecording];
#pragma mark -
#pragma mark recording
-(void) initCaptureSession
NSLog(@"Setting up capture session");
captureSession = [[AVCaptureSession alloc] init];
//----- ADD INPUTS -----
NSLog(@"Adding video input");
//ADD VIDEO INPUT
AVCaptureDevice *VideoDevice = [self frontFacingCameraIfAvailable ];
//[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (VideoDevice)
NSError *error;
videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:VideoDevice error:&error];
if (!error)
if ([captureSession canAddInput:videoInputDevice])
[captureSession addInput:videoInputDevice];
else
NSLog(@"Couldn't add video input");
else
NSLog(@"Couldn't create video input");
else
NSLog(@"Couldn't create video capture device");
//ADD AUDIO INPUT
NSLog(@"Adding audio input");
AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
NSError *error = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error];
if (audioInput)
[captureSession addInput:audioInput];
//----- ADD OUTPUTS ---
//ADD MOVIE FILE OUTPUT
NSLog(@"Adding movie file output");
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
// Float64 TotalSeconds = 60; //Total seconds
// int32_t preferredTimeScale = 30; //Frames per second
// CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale); //<<SET MAX DURATION
// movieFileOutput.maxRecordedDuration = maxDuration;
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024; //<<SET MIN FREE SPACE IN BYTES FOR RECORDING TO CONTINUE ON A VOLUME
if ([captureSession canAddOutput:movieFileOutput])
[captureSession addOutput:movieFileOutput];
//SET THE CONNECTION PROPERTIES (output properties)
[self CameraSetOutputProperties]; //(We call a method as it also has to be done after changing camera)
//----- SET THE IMAGE QUALITY / RESOLUTION -----
//Options:
// AVCaptureSessionPresetHigh - Highest recording quality (varies per device)
// AVCaptureSessionPresetMedium - Suitable for WiFi sharing (actual values may change)
// AVCaptureSessionPresetLow - Suitable for 3G sharing (actual values may change)
// AVCaptureSessionPreset640x480 - 640x480 VGA (check its supported before setting it)
// AVCaptureSessionPreset1280x720 - 1280x720 720p HD (check its supported before setting it)
// AVCaptureSessionPresetPhoto - Full photo resolution (not supported for video output)
NSLog(@"Setting image quality");
[captureSession setSessionPreset:AVCaptureSessionPresetMedium];
if ([captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) //Check size based configs are supported before setting them
[captureSession setSessionPreset:AVCaptureSessionPreset640x480];
//----- START THE CAPTURE SESSION RUNNING -----
[captureSession startRunning];
//********** CAMERA SET OUTPUT PROPERTIES **********
- (void) CameraSetOutputProperties
AVCaptureConnection *CaptureConnection=nil;
//SET THE CONNECTION PROPERTIES (output properties)
NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"5.0.0" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending)
// OS version >= 5.0.0
CaptureConnection = [movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
// if (CaptureConnection.supportsVideoMinFrameDuration)
// CaptureConnection.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
// if (CaptureConnection.supportsVideoMaxFrameDuration)
// CaptureConnection.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
// if (CaptureConnection.supportsVideoMinFrameDuration)
//
// // CMTimeShow(CaptureConnection.videoMinFrameDuration);
// // CMTimeShow(CaptureConnection.videoMaxFrameDuration);
//
else
// OS version < 5.0.0
CaptureConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[movieFileOutput connections]];
//Set landscape (if required)
if ([CaptureConnection isVideoOrientationSupported])
AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationPortrait;// AVCaptureVideoOrientationLandscapeRight; //<<<<<SET VIDEO ORIENTATION IF LANDSCAPE
[CaptureConnection setVideoOrientation:orientation];
//Set frame rate (if requried)
//CMTimeShow(CaptureConnection.videoMinFrameDuration);
//CMTimeShow(CaptureConnection.videoMaxFrameDuration);
- (void) startVideoRecording
//Create temporary URL to record to
NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
//Error - handle if requried
NSLog(@"file remove error");
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
-(void) stopVideoRecording
[movieFileOutput stopRecording];
//********** DID FINISH RECORDING TO OUTPUT FILE AT URL **********/
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
NSLog(@"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
RecordedSuccessfully = [value boolValue];
if (RecordedSuccessfully)
//----- RECORDED SUCESSFULLY -----
NSLog(@"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL])
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error)
if (error)
NSLog(@"File save error");
else
recordedVideoURL=assetURL;
];
else
NSString *assetURL=[self copyFileToDocuments:outputFileURL];
if(assetURL!=nil)
recordedVideoURL=[NSURL URLWithString:assetURL];
- (NSString*) copyFileToDocuments:(NSURL *)fileURL
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd_HH-mm-ss"];
NSString *destinationPath = [documentsDirectory stringByAppendingFormat:@"/output_%@.mov", [dateFormatter stringFromDate:[NSDate date]]];
NSError *error;
if (![[NSFileManager defaultManager] copyItemAtURL:fileURL toURL:[NSURL fileURLWithPath:destinationPath] error:&error])
NSLog(@"File save error %@", [error localizedDescription]);
return nil;
return destinationPath;
- (AVCaptureConnection *)connectionWithMediaType:(NSString *)mediaType fromConnections:(NSArray *)connections
for ( AVCaptureConnection *connection in connections )
for ( AVCaptureInputPort *port in [connection inputPorts] )
if ( [[port mediaType] isEqual:mediaType] )
return connection;
return nil;
- (AVCaptureDevice *)frontFacingCameraIfAvailable
// look at all the video devices and get the first one that's on the front
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;
for (AVCaptureDevice *device in videoDevices)
if (device.position == AVCaptureDevicePositionFront)
captureDevice = device;
break;
// couldn't find one on the front, so just get the default video device.
if ( ! captureDevice)
captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
return captureDevice;
#pragma mark -
@end
【问题讨论】:
【参考方案1】:我也有这个问题,不知道怎么解决,但我知道问题出在这里:
[captureSession addInput:audioInput];
如果你删除这行代码,它会正常工作,我认为是音频混合或一些音频问题。
我还在寻找答案。
我在这里找到了答案:answer,它有效!
但你记得加AudioToolbox.framework
,也许对你有帮助。
【讨论】:
以上是关于播放电影停止 avcapturesession 录制的主要内容,如果未能解决你的问题,请参考以下文章
当音频输入添加到 AVCaptureSession 时 AVAudioPlayer 停止
当用户尝试全屏播放时,MPMoviePlayerController 停止并重置电影 [iOS]