Stream 2 videos simultaneously Swift

拟墨画扇 提交于 2019-12-23 17:26:24

问题


I'm trying to stream two videos at the same time with swift on iphone. I already know that the AV Player can only stream one video at a time, but googling it I saw that it's still possible to stream different tracks at the same time. I also saw the picture in picture implementation. The real problem is that is all in objective-c and the code is quite old. I tried to understand it running the code as it is, but there are errors and some of the functions are deprecated. Does someone know how to do that in swift? Also, I'm streaming video from the internet so merging them before playing is not an option. Thank you!


回答1:


Swift Version

The article you referenced is an interesting method of handling multiple video playback in iOS. The article appears to be related to Apple's Stitched Stream Player Sample Project. As an exercise in Swift 2.2, I've rewritten the code on the iOS Guy article.

You can find both the view and the view controller in Swift on my gist. I'm copying below as it is best practices to not use link only answers on SO.

Custom View Player

This custom view player allows one to swap out multiple AVPlayerItem(s).

import UIKit
import AVFoundation

class MNGVideoPlayerView: UIView {

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */
    override class func layerClass () -> AnyClass {
        return AVPlayerLayer.self
    }
    func player () -> AVPlayer {
        return (self.layer as! AVPlayerLayer).player!
    }

    func setPlayer(player:AVPlayer) {
        (self.layer as! AVPlayerLayer).player = player
    }
    func setVideoFillMode(fillMode:String) {
        let playerLayer = (self.layer as! AVPlayerLayer)
        playerLayer.videoGravity = fillMode
    }

}

Multiple Video Player View Controller

This controller manages the distribution and presentation of the different AVPlayerItem(s). Check my gist repos for additional updates. (ported from original objc source @iOS Guy)

import UIKit
import AVFoundation

class MNGVideoPlayerViewController: UIViewController {



    let kTracksKey        = "tracks";
    let kStatusKey        = "status";
    let kRateKey          = "rate";
    let kPlayableKey      = "playable";
    let kCurrentItemKey   = "currentItem";
    let kTimedMetadataKey = "currentItem.timedMetadata";

    var _URL:NSURL? = nil
    var player:AVPlayer? = nil
    var playerItem:AVPlayerItem? = nil
    var playerView:MNGVideoPlayerView? = nil
    var AVPlayerDemoPlaybackViewControllerStatusObservationContext = UnsafeMutablePointer<Void>()
    var AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext = UnsafeMutablePointer<Void>()
    var AVPlayerDemoPlaybackViewControllerStatusObservation = UnsafeMutablePointer<Void>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    // MARK: - Public methods
    func setURL(url:NSURL) {
        self._URL = url
        let asset = AVURLAsset(URL: self._URL!)
        let requestedKeys = [kTracksKey,kPlayableKey]
        asset.loadValuesAsynchronouslyForKeys(requestedKeys) { () -> Void in
            self.prepareToPlayAsset(asset, withKeys: requestedKeys)
        }
    }
    func prepareToPlayAsset(asset:AVURLAsset, withKeys requestedKeys:NSArray) {
        var error:NSErrorPointer = nil

        for thisKey in requestedKeys {
            let keyStatus = asset.statusOfValueForKey(thisKey as! String, error: error)
            if keyStatus == .Failed {
                return
            }
        }

        if !asset.playable {
            return
        }
        if (self.playerItem != nil) {
            self.playerItem?.removeObserver(self, forKeyPath: kStatusKey)
            NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: self.playerItem)
        }
        self.playerItem = AVPlayerItem(asset: asset)
        self.playerItem?.addObserver(self, forKeyPath: kStatusKey, options: [.Initial,.New], context: AVPlayerDemoPlaybackViewControllerStatusObservationContext)

        if (self.player == nil) {
            self.player = AVPlayer(playerItem: self.playerItem!)
            self.player?.addObserver(self, forKeyPath: kCurrentItemKey, options: [.Initial,.New], context: AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext)
        }

        if self.player?.currentItem! != self.playerItem! {
            self.player?.replaceCurrentItemWithPlayerItem(self.playerItem!)
        }
    }

    // MARK: - Key Value Observing
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

        if context == AVPlayerDemoPlaybackViewControllerStatusObservation {

            let status:Int = (change![NSKeyValueChangeNewKey]?.integerValue)!
            if status == AVPlayerStatus.ReadyToPlay.rawValue  {
                self.player?.play()
            }
        } else if context == AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext {

            let newPlayerItem = change![NSKeyValueChangeNewKey] as? AVPlayerItem

            if newPlayerItem != nil {
                self.playerView?.setPlayer(self.player!)
                self.playerView?.setVideoFillMode(AVLayerVideoGravityResizeAspect)
            }

        } else {

            super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)

        }
    }
    /*
    // MARK: - Navigation
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}



回答2:


It looks like http://iosguy.com/2012/01/11/multiple-video-playback-on-ios/ is the best solution at the moment. Nobody tried to convert it in swift yet.




回答3:


I play multiple videos in my app at once, I just use multiple instances of AVPlayer.



来源:https://stackoverflow.com/questions/33544239/stream-2-videos-simultaneously-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!