我们有通过 bitmovin.com 编码并作为 HTTP Live Streams (Fairplay HLS) 提供的视频,但字幕虽然采用 WebVTT 格式,但作为整个文件的直接 URL 单独公开,而不是单独的片段,也不属于 HLS m3u8 播放列表的一部分。
我正在寻找如何将单独下载的外部 .vtt 文件仍包含在 HLS 流中并作为 AVPlayer 中的字幕提供的方式。
我知道 Apple 的建议是将分段 VTT 字幕包含到 HLS 播放列表中,但我现在无法更改服务器实现,所以我想澄清是否可以将字幕提供给 AVPlayer 以与 HLS 流一起播放.
关于这个主题的唯一有效帖子声称它是可能的:AVPlayer/MPMoviePlayerController 的字幕。但是,示例代码从包加载本地 mp4 文件,我正在努力使其适用于 m3u8 播放列表AVURLAsset
。实际上,我在从远程 m3u8 流中获取 videoTrack 作为asset.tracks(withMediaType: AVMediaTypeVideo)
返回空数组时遇到问题。如果这种方法适用于真正的 HLS 流,有什么想法吗?或者有没有其他方法可以使用 HLS 流播放单独的 WebVTT 字幕而不将它们包含在服务器上的 HLS 播放列表中?谢谢。
func playFpsVideo(with asset: AVURLAsset, at context: UIViewController) {
let composition = AVMutableComposition()
// Video
let videoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
let tracks = asset.tracks(withMediaType: AVMediaTypeVideo)
// ==> The code breaks here, tracks is an empty array
guard let track = tracks.first else {
Log.error("Can't get first video track")
return
}
try videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, asset.duration), of: track, at: kCMTimeZero)
} catch {
Log.error(error)
return
}
// Subtitle, some test from the bundle..
guard let subsUrl = Bundle.main.url(forResource: "subs", withExtension: "vtt") else {
Log.error("Can't load subs.vtt from bundle")
return
}
let subtitleAsset = AVURLAsset(url: subsUrl)
let subtitleTrack = composition.addMutableTrack(withMediaType: AVMediaTypeText, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
let subTracks = subtitleAsset.tracks(withMediaType: AVMediaTypeText)
guard let subTrack = subTracks.first else {
Log.error("Can't get first subs track")
return
}
try subtitleTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, asset.duration), of: subTrack, at: kCMTimeZero)
} catch {
Log.error(error)
return
}
// Prepare item and play it
let item = AVPlayerItem(asset: composition)
let player = AVPlayer(playerItem: item)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.playerViewController = playerViewController
context.present(playerViewController, animated: true) {
playerViewController.player?.play()
}
}