Видео AVPlayer не загружается постоянно - PullRequest
2 голосов
/ 04 февраля 2020

Мое приложение использует 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]

Ответы [ 3 ]

3 голосов
/ 07 февраля 2020

Во-первых, вы должны показывать предупреждение при печати «недопустимого видеообъекта», чтобы пользователь тоже получал эту информацию.

Вы пытаетесь транслировать видео. Иногда это может начаться немедленно, но в основном игроку нужно некоторое время для буферизации первых секунд, прежде чем он сможет играть.

Вам необходимо соблюдать status ваших игроков в CurrentItem. Это покажет вам, что делает ваш игрок, если он загружается, не загрузился или готов. Когда статус меняется на «readyToPlay», вы можете позвонить playerController.play()

Как наблюдать это свойство, показано здесь: { ссылка }

Редактировать: реализация наблюдателя
Объявите эту переменную в вашем классе 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()
        }
    }
})
1 голос
/ 06 февраля 2020

Код не может быть проверен как есть, поэтому просто мысленным анализом ...

Измененная часть кода следует вашему комментарию //play video. Требуется явная пересылка операций пользовательского интерфейса и переход в основной поток:

//play video
DispatchQueue.main.async {
    let player = AVPlayer(url: vid.videoURL[.Quality360p]!)
    self.playerController.player = player
    self.present(self.playerController, animated: true) {
        player.play()
    }
}
0 голосов
/ 11 февраля 2020

Ваша ссылка изменяется при прокрутке tableview. Проверьте url после прокрутки. Если все в порядке, попробуйте этот код ниже.

Для быстрого:

let url = URL(string: "https://vimeo.com/254597739")!
HCVimeoVideoExtractor.fetchVideoURLFrom(url: url, completion: { ( video:HCVimeoVideo?, error:Error?) -> Void in                
    if let err = error {                    
       print("Error = \(err.localizedDescription)")                    
       return
    }

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

    print("Title = \(vid.title), url = \(vid.videoURL), thumbnail = \(vid.thumbnailURL)")

    if let videoURL = vid.videoURL[.Quality540p] {
        let player = AVPlayer(url: videoURL)
        let playerController = AVPlayerViewController()
        playerController.player = player
        self.present(playerController, animated: true) {
            player.play()
        }
    }                            
})
...