我使用AVPlayerViewController
的AVKit
框架,直接在横向模式下播放视频。我想知道如何显示字幕。我进行了搜索,但没有找到任何解决方案。我曾经MPMoviePlayerViewController
用来播放视频,但是由于它在IOS 9和更高版本中已贬值,因此我正在使用来实现相同的功能AVKit
。
NSURL *videoURL = [NSURL URLWithString:video.videoLink];
AVPlayer *newPlayer = [AVPlayer playerWithURL:videoURL];
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = newPlayer;
int32_t timeScale = newPlayer.currentItem.asset.duration.timescale;
CMTime seektime=CMTimeMakeWithSeconds(startPlayBackTime, timeScale);
[playerViewController.player seekToTime:seektime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}
[playerViewController.player play];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[newPlayer currentItem]];
playerViewController.player.closedCaptionDisplayEnabled = YES;
[self presentViewController:playerViewController animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)
它工作正常,但问题是我无法显示字幕。我发现很少有字幕示例,但所有示例都AVPlayer
用作子视图,因此这些方法对我不起作用。
知道如何实现吗?
谢谢 !!
在过去的几个小时里一直在努力解决这个问题,希望之前有人遇到过这个问题
我下载了一个从服务器到我的文档文件夹的文件
文件存在且有效(在设备上使用iExplorer和模拟器的本地目录进行检查).将每个文件移动到我的桌面并播放没有问题.
奇怪的是,当文件(相同的视频)被添加到捆绑包时,完全相同的代码可以正常工作.
码:
print("video url string : \(video.urlString)")
// prints: /var/mobile/Containers/Data/Application/47AC756B-7A00-4FAE-9348-214972BE61BD/Documents/demo-reel.mp4
// file IS there
let asset = AVURLAsset(URL: NSURL(fileURLWithPath: video.urlString))
let keys = ["tracks","playable","duration"]
asset.loadValuesAsynchronouslyForKeys(keys, completionHandler: { () -> Void in
var error : NSError? = nil
let status = asset.statusOfValueForKey("tracks", error: &error)
switch status {
case .Failed:
print("failed \(error?.localizedDescription)")
case .Loaded:
print("loaded \(error?.localizedDescription)")
case .Loading:
print("loading \(error?.localizedDescription)")
case .Cancelled:
print("cancelled \(error?.localizedDescription)")
case .Unknown:
print("unknown \(error?.localizedDescription)")
}
prints: failed Optional("The requested URL was not found on this …
Run Code Online (Sandbox Code Playgroud) 我们有通过bitmovin.com编码的视频,并以HTTP Live Streams(Fairplay HLS)的形式提供,但字幕虽然是WebVTT格式,但是作为整个文件的直接URL单独公开,而不是单个段,并且不是HLS m3u8播放列表的一部分.
我正在寻找单独下载的外部.vtt文件如何仍然包含在HLS流中并作为AVPlayer中的副标题提供的方式.
我知道Apple的建议是将分段的VTT字幕包含在HLS播放列表中,但我现在无法改变服务器实现,所以我想澄清是否有可能为AVPlayer提供字幕以与HLS流一起播放.
关于这个主题的唯一有效帖子声称它是可能的:AVPlayer/MPMoviePlayerController的字幕.但是,示例代码从bundle加载本地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 …
Run Code Online (Sandbox Code Playgroud) 我目前正在使用 AVPlayerViewController / AVPlayer 处理 HTTP 实时流媒体视频
我正在播放支持 .m3u8 文件的视频
它播放得很好,但我的问题是,我可以像我在生成 .m3u8 文件时设置 4 种分辨率一样拥有视频数据..,我现在可以在终点改变分辨率,问题是如何获得我在端点设置的所有值。我也在 android 中播放,并且使用 Track 我能够获取所有视频信息,但是在 ios 中我如何获取包含视频的所有详细信息,例如视频的高度、轨道、视频支持的分辨率等。
我已经搜索了很多,但无法成功.. 需要帮助提前致谢
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="stereo",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,URI="audio/stereo/en/128kbit.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="stereo",LANGUAGE="dubbing",NAME="Dubbing",DEFAULT=NO,AUTOSELECT=YES,URI="audio/stereo/none/128kbit.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="surround",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,URI="audio/surround/en/320kbit.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="surround",LANGUAGE="dubbing",NAME="Dubbing",DEFAULT=NO,AUTOSELECT=YES,URI="audio/stereo/none/128kbit.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Deutsch",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="de",URI="subtitles_de.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="en",URI="subtitles_en.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Espanol",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="es",URI="subtitles_es.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Français",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="fr",URI="subtitles_fr.m3u8"
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=258157,CODECS="avc1.4d400d,mp4a.40.2",AUDIO="stereo",RESOLUTION=422x180,SUBTITLES="subs"
video/250kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=520929,CODECS="avc1.4d4015,mp4a.40.2",AUDIO="stereo",RESOLUTION=638x272,SUBTITLES="subs"
video/500kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=831270,CODECS="avc1.4d4015,mp4a.40.2",AUDIO="stereo",RESOLUTION=638x272,SUBTITLES="subs"
video/800kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1144430,CODECS="avc1.4d401f,mp4a.40.2",AUDIO="surround",RESOLUTION=958x408,SUBTITLES="subs"
video/1100kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1558322,CODECS="avc1.4d401f,mp4a.40.2",AUDIO="surround",RESOLUTION=1277x554,SUBTITLES="subs"
video/1500kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=4149264,CODECS="avc1.4d4028,mp4a.40.2",AUDIO="surround",RESOLUTION=1921x818,SUBTITLES="subs"
video/4000kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=6214307,CODECS="avc1.4d4028,mp4a.40.2",AUDIO="surround",RESOLUTION=1921x818,SUBTITLES="subs"
video/6000kbit.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=10285391,CODECS="avc1.4d4033,mp4a.40.2",AUDIO="surround",RESOLUTION=4096x1744,SUBTITLES="subs"
video/10000kbit.m3u8
Run Code Online (Sandbox Code Playgroud) 我正在尝试调试我不知道原因的崩溃。不幸的是,我所拥有的只是我从 Crashlytics 中检索到的堆栈跟踪,并且几乎找不到我的应用程序导致这种情况发生的证据,因此很遗憾我无法提供任何具体的代码示例,我在这里发布纯粹是希望之前有人遇到过这种情况。
我在通过 Crashlytics 收集的所有相关崩溃堆栈跟踪中看到,它在名为“com.apple.avkit.seekQueue”的线程上崩溃。输出如下所示:
Crashed: com.apple.avkit.seekQueue
0 libobjc.A.dylib 0x18c3e17f4 objc_object::release() + 8
1 libsystem_blocks.dylib 0x18c86fa68 _Block_release + 160
2 libdispatch.dylib 0x18c81a9a0 _dispatch_client_callout + 16
3 libdispatch.dylib 0x18c828ad4 _dispatch_queue_serial_drain + 928
4 libdispatch.dylib 0x18c81e2cc _dispatch_queue_invoke + 884
5 libdispatch.dylib 0x18c828fa8 _dispatch_queue_override_invoke + 344
6 libdispatch.dylib 0x18c82aa50 _dispatch_root_queue_drain + 540
7 libdispatch.dylib 0x18c82a7d0 _dispatch_worker_thread3 + 124
8 libsystem_pthread.dylib 0x18ca23100 _pthread_wqthread + 1096
9 libsystem_pthread.dylib 0x18ca22cac start_wqthread + 4
Run Code Online (Sandbox Code Playgroud)
由于 Crashlytics,我看到的例外是 EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000020。由此我只能假设有一个 AVPlayer 对释放或受限的内存地址做了一些事情,但堆栈跟踪没有显示除主线程中的 main.m 之外的任何其他进入我的应用程序的入口点。
FWIW,Crashlytics 还建议以下内容:
堆栈跟踪表明堆损坏可能导致您的应用程序崩溃。释放悬空指针、线程竞争或错误的指针算法很容易导致内存损坏。要记住的重要一点是,最终的崩溃可能发生在初始损坏之后很久。因此,此崩溃的堆栈跟踪可能无法提供有关代码中错误位置的任何线索。 …
我正在将应用程序的内容流式传输到RTMP服务器,并使用RPBroadcastSampleHandler。
方法之一是
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case .video:
streamer.appendSampleBuffer(sampleBuffer, withType: .video)
captureOutput(sampleBuffer)
case .audioApp:
streamer.appendSampleBuffer(sampleBuffer, withType: .audio)
captureAudioOutput(sampleBuffer)
case .audioMic:
()
}
}
Run Code Online (Sandbox Code Playgroud)
而captureOutput方法是
self.lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
// Append the sampleBuffer into videoWriterInput
if self.isRecordingVideo {
if self.videoWriterInput!.isReadyForMoreMediaData {
if self.videoWriter!.status == AVAssetWriterStatus.writing {
let whetherAppendSampleBuffer = self.videoWriterInput!.append(sampleBuffer)
print(">>>>>>>>>>>>>The time::: \(self.lastSampleTime.value)/\(self.lastSampleTime.timescale)")
if whetherAppendSampleBuffer {
print("DEBUG::: Append sample buffer successfully")
} else {
print("WARN::: Append sample buffer failed")
}
} else {
print("WARN:::The …
Run Code Online (Sandbox Code Playgroud) 根据Apple在WWDC 2019上有关此主题的演讲,AVPlayerViewController
应以模态呈现,以利用API的所有最新全屏功能。这是建议的示例代码,可从当前的UIKit视图控制器调用该代码:
// Create the player
let player = AVPlayer(url: videoURL)
// Create the player view controller and associate the player
let playerViewController = AVPlayerViewController()
playerViewController.player = player
// Present the player view controller modally
present(playerViewController, animated: true)
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,并以漂亮的全屏模式启动视频。
为了使用AVPlayerViewController
来自SwiftUI的代码,我创建了UIViewControllerRepresentable
实现:
struct AVPlayerView: UIViewControllerRepresentable {
@Binding var videoURL: URL
private var player: AVPlayer {
return AVPlayer(url: videoURL)
}
func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
playerController.player = player
playerController.player?.play()
}
func …
Run Code Online (Sandbox Code Playgroud) presentmodalviewcontroller avkit avplayerviewcontroller swiftui
当创建使用自定义视频播放器AVPlayer
+ AVPlayerLayer
+AVPictureInPictureController
的iPhone运行iOS 14(7测试版)中的视频时,应用程序进入后的背景不会自动进入子母画面模式player.start()
从UIButton的行动调用。
使用AVPlayerViewController
似乎表明AVPictureInPictureController
iOS 14 上存在问题的 问题不会重现,但我想知道是否还有其他人遇到过这个问题并知道任何解决方法。我也向 Apple 提交了这个问题rdar://8620271
示例代码。
import UIKit
import AVFoundation
import AVKit
class ViewController: UIViewController {
private let player = AVPlayer(url: URL(string: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")!)
private var pictureInPictureController: AVPictureInPictureController!
private var playerView: PlayerView!
private var playButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
playerView = PlayerView(frame: CGRect(x: 0, y: 44, width: view.bounds.width, height: 200))
playerView.backgroundColor = .black
playerView.playerLayer.player = player
view.addSubview(playerView)
playButton = UIButton(frame: CGRect(x: view.bounds.midX - …
Run Code Online (Sandbox Code Playgroud) 使用 SwiftUI VideoPlayer 时,视频上方和下方会出现黑色空间。如何删除这个黑色空间,以便只显示没有多余空间的视频。我还没有找到任何方法可以在 SwiftUI 中做到这一点。
import SwiftUI
import AVKit
struct VideoView: View {
let player = AVPlayer(url: URL(string: "https://vod-progressive.akamaized.net/exp=1606269156~acl=%2A%2F1123020046.mp4%2A~hmac=8d8e8fd9cd3c9de1b25de66bfd291f420d634f43137346daaa163bc0fbaebb22/vimeo-prod-skyfire-std-us/01/4047/11/295238750/1123020046.mp4?filename=What+Star+Wars+Can+Teach+Us+About+Swift.mp4")!)
var body: some View {
VStack {
Spacer()
VideoPlayer(player: player)
Spacer()
}
}
}
Run Code Online (Sandbox Code Playgroud) 我正在设计一个应用程序,允许用户在 SwiftUI 视图中观看特定视频。我想支持 PiP,AVPictureInPictureController.isPictureInPictureSupported() 始终返回 true,而 pipController.isPictureInPicturePossible 有时返回 true,但通常在视频实际播放时不会返回 true。我可能误解了如何使用 AVPictureInPictureController。
我的应用程序使用以下代码初始化一个称为 FullScreenVideoView 的视图:
init(player: KHKVideoPlayer, aspectRatio: CGFloat, presentingViewController pvc: UIViewController?) {
self.aspectRatio = aspectRatio
self.pvc = pvc
self.model = FullScreenVideoViewerModel(player: player)
self.playerController = KHKPlayerController(player: player.avPlayer, cornerRadius: 0)
if AVPictureInPictureController.isPictureInPictureSupported() {
self.pipController = AVPictureInPictureController(playerLayer: AVPlayerLayer(player: player.avPlayer))!
}
self.isMuted = player.avPlayer.isMuted
}
Run Code Online (Sandbox Code Playgroud)
然后,在视图主体内,它通过调用初始化程序中定义的playerController来显示视频:
playerController
.frame(height: aspectRatio * geometry.size.width)
.onTapGesture {
if self.model.player.avPlayer.isPlaying {
self.model.pause()
} else {
self.model.play()
}
}
Run Code Online (Sandbox Code Playgroud)
PlayerController 是 AVPlayerViewController 的包装器:
struct KHKPlayerController: UIViewControllerRepresentable {
typealias UIViewControllerType = …
Run Code Online (Sandbox Code Playgroud)