Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playing video in web view unexpectedly ends background video recording?

I am using a WKWebView to display a fullscreen YouTube video in my app, and a AVCaptureSession to record audio and video in the background whilst browsing and playing videos on YouTube. The capture session begins when a button is pressed. However, whilst a recording is in process, when a YouTube video is selected and starts playing in fullscreen, it immediately ends the recording unexpectedly as the delegate method that handles the ending of a recording is called.

Please could someone explain to me how to solve this problem? Not too sure if this is completely related, but I got error messages such as _BSMachError: (os/kern) invalid capability (20) _BSMachError: (os/kern) invalid name (15) and Unable to simultaneously satisfy constraints., though the latter one seems to be referencing a separate AutoLayout issue. Any help would be greatly appreciated.

Also, I have tried using UIWebView instead of WKWebView. When I use UIWebView, the problem is that the YouTube video will not even play when the video is recording. It will just open and stay at 0:00 on a black screen.

Here is the button pressed to initially start the recording.

- (void) buttonClickedStart:(UIButton*)sender //button to start/end recording {
    if (!WeAreRecording) {
        [self setupVideoCapture]; 
        //----- START RECORDING -----
        WeAreRecording = YES;
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];

        //Create temporary URL to record the video to for later viewing
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *basePath = [paths objectAtIndex:0];
        NSString *outputPath = [[NSString alloc] initWithFormat:@"%@", [basePath stringByAppendingPathComponent:@"output.mp4"]];
        if ([[NSFileManager defaultManager] isDeletableFileAtPath:outputPath])
            [[NSFileManager defaultManager] removeItemAtPath:outputPath error:NULL];
        NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
        [MovieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
        self.outputURLs = outputURL;
    }
    else {
        //----- STOP RECORDING -----
        WeAreRecording = NO;
        [MovieFileOutput stopRecording];
    }
}

This is the method called when the button is pressed. It sets up and starts the capture session denoted as CaptureSession.

- (void)setupVideoCapture { 
    // Sets up recording capture session
    CaptureSession = [[AVCaptureSession alloc] init];

    // Add video input to capture session
    AVCaptureDevice *VideoDevice = [AVCaptureDevice     defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (VideoDevice) {
        NSError *error;
        VideoInputDevice = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionFront] error:&error];
        if (!error) {
            if ([CaptureSession canAddInput:VideoInputDevice])
                [CaptureSession addInput:VideoInputDevice];
         }
    }

    // Add audio input to capture session
    AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice   defaultDeviceWithMediaType:AVMediaTypeAudio];
    NSError *error = nil;
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput  deviceInputWithDevice:audioCaptureDevice error:&error];
    if (audioInput) {
        [CaptureSession addInput:audioInput];
    }

    // Add movie file output to the capture session
    MovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
    [MovieFileOutput setMovieFragmentInterval:kCMTimeInvalid];
    if ([CaptureSession canAddOutput:MovieFileOutput])
        [CaptureSession addOutput:MovieFileOutput];

    // Set the output properties (you don't really need to see this code)
    [self CameraSetOutputProperties]; // (We call a method as it also has to be done after changing camera)
    [CaptureSession setSessionPreset:AVCaptureSessionPresetMedium];

    //----- START THE CAPTURE SESSION RUNNING -----
    [CaptureSession startRunning];
}

This is where the WKWebView is declared and set up.

- (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];

        // Add recording button
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;
        CGRect rect = CGRectMake(0, 0, screenSize.width, 337);
        UIButton *start = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [start addTarget:self action:@selector(buttonClickedStart:) forControlEvents:UIControlEventTouchUpInside];
        [start setFrame:CGRectMake(30, 338, 35, 35)];
        [start setTitle:@"" forState:UIControlStateNormal];
        [start setExclusiveTouch:YES];
        [start setBackgroundImage:[UIImage imageNamed:@"start.png"] forState:UIControlStateNormal];
        [self.view addSubview:start];

        // Add web view
        webView = [[WKWebView alloc] initWithFrame:rect];
        [self.view addSubview:webView];
        NSString *webSite = @"http://www.youtube.com";
        NSURL *url = [NSURL URLWithString:webSite];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        webView.navigationDelegate = self;
        webView.UIDelegate = self;
        [webView loadRequest:request]; // Load up Youtube           
        [self.view addSubview:webView];
}
like image 350
Mateo Encarnacion Avatar asked Apr 29 '16 00:04

Mateo Encarnacion


People also ask

How can I make WebView keep a video or audio playing in the background?

After searching a lot, I found this thread. I did something similar: Just extend WebView and override onWindowVisibilityChanged . This way, the audio continues to play if the screen is locked or another app is opened.

Can we play YouTube in background?

For Android devices, you can play YouTube videos in the background via Google Chrome or picture in picture mode.

Why is YouTube background play not working?

Restart the YouTube app or reboot your device If the YouTube app or your mobile device has been running for some time, there may not be enough resources for background play to work smoothly. Try closing the YouTube app or rebooting your phone.


2 Answers

Looks like the only things that are missing is setting the mix with others option and play and record category on the audio session.

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];

Edit: Setup a simple test and it works, hope this helps!

like image 121
hola Avatar answered Oct 22 '22 13:10

hola


The cause of the

_BSMachError: (os/kern) invalid capability (20) _BSMachError: (os/kern) invalid name (15)

may be due to the fact that Apple introduced App Transport Security which enforces the use of 'HTTPS' URLs. Although you can modify your info.plist to make an exception, for legacy URLS, they highly recommend using HTTPS for any new URLs.

In your case that is an easy fix if you just update your youtube URL to 'https:'

like image 1
chrissukhram Avatar answered Oct 22 '22 13:10

chrissukhram