Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 4 - Trying to display AWS video url from backend in AVPlayerViewController not working, get weird error

I have a tableview which sets a UIImage to hold either an image url from AWS or a thumbnail generated from a video URL also from AWS. The video url refuses to display in my tableview and it throws this error in the debugger.

2017-12-29 12:20:37.053337-0800 VideoFit[3541:1366125] CredStore - performQuery - Error copying matching creds.  Error=-25300, query={
    class = inet;
    "m_Limit" = "m_LimitAll";
    "r_Attributes" = 1;
    sync = syna;
}

When I click the cell to display either the image or video url, it segues to the video player correctly and then I get the error again and the triangular start button has a line through it signifying that there is no video to be played.

videoplayererror

But when I print the url it has successfully passed so that is not the issue, the issue is AVPlayer can't handle my AWS video url for some reason. It is an https link so that means it must be secure but I already set my arbitrary loads to true

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Here is some code for displaying my videos in the videoPlayer VC and also the thumbnail generator function, perhaps there is some issue lying with these?

import UIKit
import AVKit
import MediaPlayer

class VideoPlayerVC: AVPlayerViewController {

    var urlToPlay: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        print("Here is the url ---> \(String(describing: urlToPlay))")
        playVideo()
    }

    private func playVideo() {

        guard let urlFromString = urlToPlay else { print("No url to play") ;return }
        let url = URL(string: urlFromString)
        print("Here is the url to play ---> \(String(describing: url))")
        let asset: AVURLAsset = AVURLAsset(url: url!)
        let item: AVPlayerItem = AVPlayerItem(asset: asset)
        let player: AVPlayer = AVPlayer(playerItem: item)

        self.player = player
        self.showsPlaybackControls = true

        self.player?.play()
    }
}

This is how I make the thumbnail, when my cellforRow atIndexPath method runs it throws this error for every video object in the tableview.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if let cell = tableView.dequeueReusableCell(withIdentifier: "sortedExerciseCell") as? SortedExerciseCell! {
        // Do if check for videoURI and imageURI
        if selectedExerciseArray[indexPath.row].imageURI != nil {
            if let imageURI = URL(string: selectedExerciseArray[indexPath.row].imageURI!) {
                print("It's a photo!")
                // Using DispatchQueue.global(qos: .background).async loads cells in background
                DispatchQueue.global(qos: .background).async {
                    let data = try? Data(contentsOf: imageURI)

                    DispatchQueue.main.async {
                        cell.exerciseImg.image = UIImage(data: data!)
                    }
                }
            }
        } else {
            if let videoURI = URL(string: selectedExerciseArray[indexPath.row].videoURI!) {
                print("It's a video!")
                print(videoURI)
                DispatchQueue.global(qos: .background).async {
                    DispatchQueue.main.async {
                        cell.exerciseImg.image = self.thumbnailForVideoAtURL(url: videoURI) 
                     // for every video object the above error is thrown!!!
                    }
                }
            }
        }
        cell.exerciseName.text = selectedExerciseArray[indexPath.row].name
        return cell
    } else {
        return UITableViewCell()
    }
}

// Used to just display the video thumbnail in cell, when clicked on will display video as needed

private func thumbnailForVideoAtURL(url: URL) -> UIImage? {

    let asset = AVAsset(url: url)
    let assetImageGenerator = AVAssetImageGenerator(asset: asset)

    do {
        print("Doing the video thumbnail from backend")
        let imageRef = try assetImageGenerator.copyCGImage(at: CMTimeMake(1, 60) , actualTime: nil)
        return UIImage(cgImage: imageRef)
    } catch {
        print("This is failing for some reason")
        print("error")
        return nil
    }
}

I've looked at similar questions on stack overflow about this but none seem to give a complete answer on how to solve this problem, most chalking it up to an iOS 11 bug that can't be fixed or transport security (Already have arbitrary loads on so this can't be the issue..) anyone else have any approaches that might work?

  • Important note - My backend developer can only view the video url's from a webpage, in other words he must make a basic website to display the video after downloading it from the web. I'm not sure if this is standard procedure for handling video url's from AWS but I decided to try loading the url with "loadHTMLString" in a custom UIViewController conforming to WKUIDelegate, I see the video but the same situation happens where the triangular start button is crossed out signifying no video can be played. I'm not really sure what else I can try at this moment, any help is appreciated.

  • Here is one of the links I've pulled from my backend. https://videofitapptestbucket.s3.us-west-2.amazonaws.com/100001427750

like image 586
Jumpman987 Avatar asked Jan 18 '26 22:01

Jumpman987


1 Answers

It seems that your problem is in file extension. DMS is not recognized by OS, it throws when creating image with assetgenerator.

Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo={NSLocalizedFailureReason=This media format is not supported., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x6040000534d0 {Error Domain=NSOSStatusErrorDomain Code=-12847 "(null)"}}

Rename your files on server. The mp4 extension seems to work just fine with your file.

Also, subclassing AVPlayerViewController is generally not that great idea as Apple says that it will result in undefined behavior. (read: random mess). I would suggest to use class that have AVPlayer inside.

like image 89
Juraj Antas Avatar answered Jan 21 '26 10:01

Juraj Antas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!