skip to Main Content

I have an ipfs encrypted video URL.
I am not able to play video in avplayer but URL plays well in webview.
here is URL: https://ipfs.moralis.io:2053/ipfs/QmUjWnQZVVNmTSVak2QDhTxMkn3dPQozxawa1sm3jE5bLr

let currentURL = URL(string: "https://ipfs.moralis.io:2053/ipfs/QmUjWnQZVVNmTSVak2QDhTxMkn3dPQozxawa1sm3jE5bLr")!
let playerItem = AVPlayerItem(url: currentURL)
playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions(), context: nil)
player = AVPlayer(playerItem: playerItem)let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.avplayerUIView.bounds
self.avplayerUIView.layer.addSublayer(playerLayer)
player.play()

Also, I have used AVUrlAssets with video extension and video codecs but still, video is not playing

let mimeType = "video/mp4; codecs="avc1.42E01E, mp4a.40.2""
let asset: AVURLAsset = AVURLAsset(url: videoURL!, options: ["AVURLAssetOutOfBandMIMETypeKey" : mimeType])

2

Answers


  1. Strange. It seems AVPlayerLayer can not resolve video. If you remove playerLayer, you will hear audio is playing fine.

    My solution is using AVPlayerViewController.

    let vc = AVPlayerViewController()
    vc.view.frame = view.bounds
    vc.player = player
    player.play()
    present(vc, animated: true) // or use as a child view controller by embedding in a container view 
    
    Login or Signup to reply.
  2. It’s a good practice to handle errors from your code to get info about the problem so lets make next error handler:

    class ErrorObserver: NSObject {
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
            guard let player = object as? AVPlayer, let error = player.currentItem?.error, let keyPath = keyPath else {
                return
            }
            print("Key:", keyPath)
            print("Error:", error)
        }
    }
    
    let errorObserver = ErrorObserver()
    
    ...
    
    // Add observer AVPlayerItem status
    player.addObserver(errorObserver, forKeyPath: #keyPath(AVPlayer.currentItem.status), options:[.new], context: nil)
    

    If you run your code it produces next error:

    Key: currentItem.status
    Error: Error Domain=AVFoundationErrorDomain Code=-11850 "Operation Stopped" UserInfo={NSLocalizedFailureReason=The server is not correctly configured., NSLocalizedDescription=Operation Stopped, NSUnderlyingError=0x600003bbc060 {Error Domain=NSOSStatusErrorDomain Code=-12939 "(null)"}}
    

    "The server is not correctly configured." is often related to the HTTP range requests issue on a server side because supporting downloading by ranges is required to play media from the Internet.

    Lets check this with curl:

    $ curl -I https://ipfs.moralis.io:2053/ipfs/QmUjWnQZVVNmTSVak2QDhTxMkn3dPQozxawa1sm3jE5bLr
    HTTP/2 200 
    date: Fri, 05 Aug 2022 09:48:23 GMT
    content-type: video/mp4
    content-length: 4835525
    cf-ray: 735e9de8d95c9290-FRA
    accept-ranges: bytes
    ...
    

    As you can see from the response the server supports ranges – "accept-ranges: bytes".

    Lets check the partial request:

    $ curl https://ipfs.moralis.io:2053/ipfs/QmUjWnQZVVNmTSVak2QDhTxMkn3dPQozxawa1sm3jE5bLr -i -H "Range: bytes=0-1023"
    HTTP/2 200 
    date: Fri, 05 Aug 2022 09:50:05 GMT
    content-type: video/mp4
    content-length: 4835525
    cf-ray: 735ea066cfd61649-MUC
    accept-ranges: bytes
    ...
    

    The server responds with HTTP/2 200 and the full content length but the response must be like this:

    HTTP/2 206 Partial Content
    Accept-Ranges: bytes
    Server: UploadServer
    Aka-c-hit: cache-hit
    Content-Range: bytes 0-1023/253755577
    Content-Length: 1024
    Connection: keep-alive
    Content-Type: video/mp4
    ...
    

    So that your server doesn’t support HTTP ranges requests and AVPlayer can’t play your mp4 video.

    You can resolve the issue with two ways:

    1. Change the servers’s settings to support HTTP range requests.
    2. Programmatically download video and save it to a local file and after you can play it from file URL.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search