2

I'm trying to play a video file from a server, the file plays in the simulator, but it doesn't in the actual device. When the item's status changes (failed) the error message is:

Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo=0x15542db0 {NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x156f49f0 "The operation couldn’t be completed. (OSStatus error -12847.)", NSLocalizedFailureReason=This media format is not supported.}

I've read in this question that the file should have either an extension or the server should reply with the correct mime type, however in this situation neither is possible.

I'd like to know if there's a way to modify the server response or provide the mime type programmatically, either with AVPlayer or MPMoviePlayerController. Thank you in advance.

Community
  • 1
  • 1
Emanuel
  • 1,981
  • 1
  • 20
  • 28
  • AFAIK the networking layer below `AVPlayer` (therefore also below `MPMoviePlayerController`) is entirely transparent to the user. Hence there is no way to modify the communication on that layer. The only solution I can see is a local proxy as used by several YouTube video playback apps. – Till Dec 17 '13 at 00:17
  • 1
    @Till Did you mean to say entirely opaque? – Kyle Redfearn Jul 30 '21 at 15:15
  • 1
    @KyleRedfearn indeed I meant to say entirely opaque, ty. – Till Sep 07 '21 at 16:27

3 Answers3

2

I implemented a NSURLProtocol with a custom scheme to intercept the call and modify the response:

https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSURLProtocol_Class/Reference/Reference.html

Emanuel
  • 1,981
  • 1
  • 20
  • 28
2

WebKit handle this by a Private AVURLAsset option: AVURLAssetOutOfBandMIMETypeKey, this option is used when you specify a MIME type in the HTML's video tag,

You can use this option like:

NSString * mimeType = @"video/mp4";

// or even with codecs
mimeType = @"video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"";

// create asset
AVURLAsset * asset = [[AVURLAsset alloc] initWithURL:url options:@{@"AVURLAssetOutOfBandMIMETypeKey": mimeType}];

// create AVPlayer with AVURLAsset
AVPlayer * player = [AVPlayer playerWithPlayerItem:[AVPlayerItem playerItemWithAsset:asset]];

Since it is a private key, you may want to obfuscate it if you plan to submit it to AppStore.

The WebKit source can be found here: https://opensource.apple.com/source/WebCore/WebCore-7604.1.38.1.6/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm.auto.html

naituw
  • 1,087
  • 10
  • 14
0

here is Swift 4.2 code:

let mimeType = "video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\""
let asset: AVURLAsset = AVURLAsset(url: videoURL, options: ["AVURLAssetOutOfBandMIMETypeKey" : mimeType])
let player = AVPlayer(playerItem: AVPlayerItem(asset: asset))
perudot
  • 1
  • 1