1

我有一个 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
4

1 回答 1

0

我也有这个问题,不知道怎么解决,但是我知道问题出在这里:

[captureSession addInput:audioInput];

如果你删除这行代码,它会正常工作,我认为这是音频混合或一些音频问题。

我还在寻找答案。

我在这里找到了答案:答案,它有效!

但你记得添加AudioToolbox.framework,也许对你有帮助。

于 2012-12-23T14:39:11.767 回答