WKWebKit Issue Playing Embedded Video

Hello,


I'm in the midst of converting some web views in our app from UIWebView to WKWebView and I've been running into some issues with playing html5 video. I built a small test program to narrow down the problem, and I've come to the point where I have an html file and a video file bundled in a simple app. I load the html file into the WKWebView like this:


NSString *videoPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
[self.wkWebView loadFileURL:[NSURL fileURLWithPath:videoPath] allowingReadAccessToURL:[NSURL fileURLWithPath:[videoPath stringByDeletingLastPathComponent]]];


The html loaded is very simple...


<html>
<head></head>
<body>
    <center><h1>Inline Video Tester</h1></center>
    <center><img src="./test_img.jpg"></center>
    <center><video src="./test.mp4" autoplay playsinline></video></center>
</body>
</html>


(Note I am also loading an image to prove that the relative pathing was working correctly. )


This works fine on all the iOS 10 devices I've tried. It also works fine on any simulator - both iOS 9 and iOS 10. The only place it will not load the video is on my old iPad 2 which is running iOS 9.3.5. On that device, the video refuses to load or play in WKWebView. I can see the rest of the html page load fine, but the video isn't there at all. The only clue I can see in the console is this:


Apr 27 15:24:59 Pad-2 kernel[0] <Notice>: Sandbox: com.apple.WebKit(1307) deny(1) file-issue-extension /private/var/containers/Bundle/Application/40EEC181-1DE9-4005-A5CB-6E1AC38C184A/InlineVideoTester.app

Apr 27 15:24:59 iPad-2 kernel[0] <Notice>: Sandbox: com.apple.WebKit(1307) deny(1) file-issue-extension /private/var/containers/Bundle/Application/40EEC181-1DE9-4005-A5CB-6E1AC38C184A/InlineVideoTester.app/test.mp4

Apr 27 15:24:59 iPad-2 kernel[0] <Notice>: Sandbox: mediaserverd(42) deny(1) file-read-data /private/var/containers/Bundle/Application/40EEC181-1DE9-4005-A5CB-6E1AC38C184A/InlineVideoTester.app/test.mp4

Apr 27 15:24:59 iPad-2 kernel[0] <Notice>: Sandbox: mediaserverd(42) deny(1) file-read-data /private/var/containers/Bundle/Application/40EEC181-1DE9-4005-A5CB-6E1AC38C184A/InlineVideoTester.app/test.mp4

Apr 27 15:24:59 iPad-2 kernel[0] <Notice>: Sandbox: mediaserverd(42) deny(1) file-read-data /private/var/containers/Bundle/Application/40EEC181-1DE9-4005-A5CB-6E1AC38C184A/InlineVideoTester.app/test.mp4


I've tried googling these sandbox deny messages, but found nothing useful. Also worth mentioning that if I switch back to UIWebView with the exact same html and video file, it loads and plays fine on the iPad 2. I'm at a loss. Anyone have any idea why this video is getting denied in the sandbox? Let me know if there's any other info I can provide.


Thank you,

-Dan

Replies

Wanted to add a quick reply because I finally found a workaround to this. It appears that simply initing an AVPlayer with a path to the folder that contains the media files is enough to allow the sandbox to load them in the WKWebView. This is what I ended up doing directly before loading the html itself:


NSString *accessPath = [htmlFilePath stringByDeletingLastPathComponent];
// Strange workaround to make html5 videos play on iOS 9 devices.
self.workaroundPlayer = [AVPlayer playerWithURL:[NSURL fileURLWithPath:accessPath]];
[self.webView loadFileURL:[NSURL fileURLWithPath:htmlFilePath] allowingReadAccessToURL:[NSURL fileURLWithPath:accessPath]];


That's it. The path used to init AVPlayer isn't a valid media file, and you don't need to try to play the AVPlayer or anything. Just init it, and then load your html, and it works... Hopefully this saves someone some time and headaches.

My two cents to this issue:

When loading resources from the application, the url of the resource needs to be included.


let videoURL = Bundle.main.url(forResource: "myvideo", withExtension: ".mp4")

let html =

"""

<!DOCTYPE html>

<html>

<head>

<title>A video file</title>

</head>

<body>

<video width="100%" controls>

<source src="\(videoURL?.absoluteString)" type="video/mp4">

</video>

</body>

</html>

""";


webView.loadHTMLString(html, baseURL: videoURL )