ios - AVPlayer 视频始终无法加载

标签 ios swift avplayer vimeo

我的应用程序使用 AVPlayer 来播放我的视频,但它们并非每次都播放。我只是在某些视频上出现黑屏。然而,不播放的视频每次都不一样。我不明白为什么这一分钟还有效,下一分钟就不行了。我正在使用 HCVimeoVideoExtractor 来从 Vimeo 中提取视频。

import UIKit
import HCVimeoVideoExtractor
import Foundation
import AVKit
import AVFoundation

class Arms : UITableViewController{

    @IBOutlet var Tableview: UITableView!

    //video outlet
    let playerController = AVPlayerViewController()

    //@IBOutlet var mypic: UIImageView!

    let sectionName = ["Day 0","Day 1","Day 2","Day 3","Day 4","Day 5","Day 6","7"]

    let foodTitleArray = ["1 and a Half Cable Bicep Curl", "Barbell Bicep Curls", "Cable Bicep Curl","Dumbbell Bicep Curl","Bench Press Close Grip","Across The Body Tricep Extension","EZ Bar Curl", "Dumbbell Hammer Curl", "Low Pulley Cable Curl", "Preacher Curl Machine", "Skull Crusher", "Straight Bar Tricep Extension", "Rope Tricep Extension"]

    let foodImageArray = ["Bicep Curl 1 and half Cable", "Bicep Curl Barbell", "Bicep Curl Cable","Bicep Curl Dumbbell","Close Grip Bench Press","Cross body tricep extension","EZ Bar Curl", "Hammer Curl Dumbbell", "Low Cable Pulley Curl", "Preacher Curl Machine", "Skull Crusher", "Tricep extension Cable", "Tricep Extension rope"]


    var rowselected = Int()


    //-----vids-----
    //video links
    var calledVideo: String?

    let vids = ["https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345","https://vimeo.com/12345", "https://vimeo.com/12345", "https://vimeo.com/12345", "https://vimeo.com/12345"]
    //-----vids-----


    override func viewDidLoad() {
        super.viewDidLoad()
    }


    @IBAction func Back(_ sender: Any) {

        NotificationCenter.default.removeObserver(self)

        self.dismiss(animated: true, completion: nil)
    }


    //setting up tableview rows
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //return sectionName.count
        return foodTitleArray.count
    }


    //what cell is & how it looks
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = Tableview.dequeueReusableCell(withIdentifier: "cellarms") as! UITableViewCell1


        // cell.foodImage.image = UIImage(named: foodImageArray[indexPath.row] + ".jpg") //this is origionally how memory images are used added to cell. this way caches the images building memory.
        cell.foodTitle.text = foodTitleArray[indexPath.row] //this is how to the uitableviews titles are added to cells

        //shows the images in cells without storing image in cache
        let bundlePath = Bundle.main.path(forResource: foodImageArray[indexPath.row], ofType: "jpg")
        let image = UIImage(contentsOfFile: bundlePath!)
        cell.foodImage.image = image

        return (cell)
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        rowselected = indexPath.row

        //indexpath.row is the code to get a number of the row selected this number then is selected from vids array and sets calledvideo to this number.
        print(indexPath.row)
        let number = indexPath.row
        calledVideo = vids[number]
        print(calledVideo)
        geturl()


        //making desleected row not highlighted
        tableView.deselectRow(at: indexPath, animated: true)
    }

    //Getting url info for video by using exractor
    func geturl() {
        if let url = URL(string: calledVideo!) {
            HCVimeoVideoExtractor.fetchVideoURLFrom(url: url, completion: { ( video:HCVimeoVideo?, error:Error?) -> Void in
                if let err = error {
                    DispatchQueue.main.async() {
                        let alert = UIAlertController(title: "Error", message: err.localizedDescription, preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                        self.present(alert, animated: true, completion: nil)
                    }
                    return
                }


                guard let vid = video else {
                    print("Invalid video object")
                    return
                }



                //play video
                let player = AVPlayer(url: vid.videoURL[.Quality360p]!)
                self.playerController.player = player
                self.present(self.playerController, animated: true) {
                    player.play()
                }
            })   
        }
    }
}

这是一个不同的视频,每次在我身上都会被取消。这似乎是完全随机的。以下是我在取消视频时发生的错误的一个示例:

Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=https://gcs-vimeo.akamaized.net/exp=1581445783~acl=%2Fvimeo-prod-skyfire-std-us%2F01%2F3120%2F14%2F365604762%2F1507711789.mp4~hmac=ac26b711525132b93ce5b4c33db5f04efc84feab53f3c07ec324d15962a9f5dd/vimeo-prod-skyfire-std-us/01/3120/14/365604762/1507711789.mp4?source=1, NSErrorFailingURLKey=https://gcs-vimeo.akamaized.net/exp=1581445783~acl=%2Fvimeo-prod-skyfire-std-us%2F01%2F3120%2F14%2F365604762%2F1507711789.mp4~hmac=ac26b711525132b93ce5b4c33db5f04efc84feab53f3c07ec324d15962a9f5dd/vimeo-prod-skyfire-std-us/01/3120/14/365604762/1507711789.mp4?source=1, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <A7D7517F-1F77-495B-80A1-2F61FE5B723D>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <A7D7517F-1F77-495B-80A1-2F61FE5B723D>.<1>, NSLocalizedDescription=cancelled} [-999]

最佳答案

首先,您应该在打印“无效视频对象”时显示警报,以便用户也能获取此信息。

您尝试流式传输视频。有时这可能会立即开始,但大多数情况下玩家需要一些时间来缓冲前几秒才能玩。

您需要观察玩家 currentItem 的状态。这将向您显示播放器正在做什么,是否正在加载、加载失败或已准备就绪。当状态变为“readyToPlay”时,您可以调用playerController.play()

如何观察此属性如下所示: https://stackoverflow.com/a/47787854

编辑:观察者实现
在 ViewController 类中声明此变量:

var observer: NSKeyValueObservation? {
    willSet {
        guard let observer = observer else { return }
        observer.invalidate()
    }
}

替换此代码:

//play video
let player = AVPlayer(url: vid.videoURL[.Quality360p]!)
self.playerController.player = player
self.present(self.playerController, animated: true) {
    player.play()
}

具有以下内容:

let url = vid.videoURL[.Quality360p]!
// Create asset to be played
let asset = AVAsset(url: url)

let assetKeys = [
    "playable",
    "hasProtectedContent"
]
// Create a new AVPlayerItem with the asset and an
// array of asset keys to be automatically loaded
let playerItem = AVPlayerItem(asset: asset,
                          automaticallyLoadedAssetKeys: assetKeys)

// Associate the player item with the player
let player = AVPlayer(playerItem: playerItem)
self.playerController.player = player

// Register as an observer of the player item's status property
self.observer = playerItem.observe(\.status, options:  [.new, .old], changeHandler: { (playerItem, change) in
    if playerItem.status == .readyToPlay {
        self.present(self.playerController, animated: true) {
            player.play()
        }
    }
})

关于ios - AVPlayer 视频始终无法加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60047990/

相关文章:

ios - 如果堆分配内存达到5GB,iOS应用程序会拒绝吗

iphone - 委托(delegate)IBA行动

javascript - iOS Safari 13.1 对 DeviceMotionEvent 的权限

swift - 节点名称被 USDZ 模型覆盖

ios - 如何删除 UITableView 分隔符(Xcode)

MACH_TASK_BASIC_INFO 的 Swift 指针问题

objective-c - AVPlayer 在模拟器上可以播放,但在真实设备上却无法播放

ios - 在选项卡栏 Controller 中将数据从一个 View 传递到另一个 View 未按时传递

ios - 检测 AVPlayer 何时播放

ios - AVPlayer播放音频时如何添加iPod EQ?