我试图用iphone快速同时播放两个视频。我已经知道AV播放器一次只能传输一个视频,但谷歌搜索它我看到它仍然可以同时流式传输不同的音轨。我也看到了画中画的实现。真正的问题是,所有这些都是客观的,而且代码很老。我试图理解它按原样运行代码,但是有错误,有些函数已被弃用。 有人知道如何在swift中做到这一点吗?此外,我从互联网流式传输视频,因此在播放前合并它们不是一种选择。 谢谢!
答案 0 :(得分:2)
您引用的article是一种在iOS中处理多个视频播放的有趣方法。这篇文章似乎与Apple的Stitched Stream Player Sample Project有关。作为Swift 2.2中的练习,我在iOS Guy文章中重写了代码。
您可以在my gist上的Swift中找到视图和视图控制器。我正在下面复制,因为最好不要在SO上使用仅链接答案。
此自定义视图播放器允许用户换出多个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
}
}
此控制器管理不同AVPlayerItem
(s)的分发和呈现。检查my gist repos以获取其他更新。 (从原始objc源@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.
}
*/
}
答案 1 :(得分:1)
我一次在我的应用中播放多个视频,我只使用多个AVPlayer实例。
答案 2 :(得分:0)
目前看来http://iosguy.com/2012/01/11/multiple-video-playback-on-ios/是最佳解决方案。没有人试图快速转换它。