使用AVComposition时如何避免Airplay冻结?

时间:2017-04-19 18:43:51

标签: avfoundation airplay subtitle avkit avcomposition

我的代码如下:

//init mix composition
let mixComposition = AVMutableComposition()

//video asset
let videoAsset = AVURLAsset(url: VIDEO_URL)
let videoTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
try? videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaTypeVideo).first!, at: kCMTimeZero)

//audio track
let audioTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
try? audioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaTypeAudio).first!, at: kCMTimeZero)

//subtitles
let path = Bundle.main.path(forResource: "subtitle", ofType: "vtt")!
let subtitleAsset = AVAsset(url: URL(fileURLWithPath: path))
let subtitleTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeText, preferredTrackID: kCMPersistentTrackID_Invalid)
try? subtitleTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: subtitleAsset.tracks(withMediaType: AVMediaTypeText)[0], at: kCMTimeZero)

 //setup player and play
 let item = AVPlayerItem(asset: videoAsset)
 let player = AVPlayer(playerItem: item)
 self.player = player
 self.player?.allowsExternalPlayback = true
 self.player?.usesExternalPlaybackWhileExternalScreenIsActive = true
 self.player?.play()

当被问及videoAsset.isCompatibleWithAirPlayVideo是否返回true时。当你加载应用程序时它一切顺利,直到你进入Airplay模式,屏幕冻结,直到你再次退出Airplay模式。

如果您要将mixComposition更改为videoAsset,则这是完全不同的行为。现在一切正常,但你没有外部字幕。

是否有其他人遇到过这个问题以及解决方法。我的最终目标是在mp4视频中加入外部字幕。

1 个答案:

答案 0 :(得分:0)

我的应用程序中的代码几乎与您的相同,并且它在Airplay模式下工作,所以我认为你几乎就在那里。

我从网络服务器加载视频,音频和vtt字幕,并遇到两个主要挑战:

  1. 音频无法播放,除非它来自https-host而不管plist设置(视频播放从http主机播放得很好)
  2. 字幕只持续10-12分钟的电影。解决方案是使用FileManager
  3. 从.documentDirectory下载字幕和加载

    与您的代码的唯一区别是我初始化AVPlayerViewController并将播放器设置为AVPlayer:

    var moviePlayer = AVPlayerViewController()
    moviePlayer.player = player
    

    然后呈现moviePlayer

    self.view.window?.rootViewController?.present(self.moviePlayer, animated: true, completion : { self.moviePlayerFinishedLoading() } 
    self.moviePlayer.player?.play()
    

    希望这有帮助