将 AVPlayerViewController.player 设置为 nil 会中断隐藏式字幕
Setting AVPlayerViewController.player to nil breaks closed captions
根据 Apple 的文档,如果您想在后台播放视频的音频内容,则必须在移动应用程序时断开 AVPlayer
与其 AVPlayerViewController
或 AVPlayerLayer
的连接到后台以防止音频自动暂停:
我注意到在 iOS 13 中,这样做会导致隐藏式字幕中断。我创建了一个新项目(单视图应用程序)来为这个问题创建一个最小的重现案例。我的情节提要由一个视图和一个按钮组成,按钮作为一个动作连接到我的视图控制器 ("playPressed")。这是我的 ViewController.m
:
的代码
//
// ViewController.m
// AVPlayerViewControllerBug
//
// Created by Steven Barnett on 9/27/19.
// Copyright © 2019 BlueFrame Tech. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
{
@private
AVPlayerViewController *controller;
AVPlayer *player;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
controller = [[AVPlayerViewController alloc] init];
player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:@"https://vcloud.blueframetech.com/file/hls/143758.m3u8"]];
controller.player = player;
[player addObserver:self forKeyPath:@"rate" options:0 context:nil];
}
- (IBAction)playPressed:(id)sender {
[self presentViewController:controller animated:YES completion:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// Since we're ONLY observing "rate" on the player, assume
// that's what changed to call this
AVPlayer *player = (AVPlayer*)object;
if (player.rate == 0)
{
// Unbind the player from the view controller when paused
controller.player = nil;
// Since I haven't built custom controls for the player,
// when it's unbound there's no way to hit the play
// button. So we'll just start playing after a timer
// has elapsed
[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:NO block:^(NSTimer * _Nonnull timer) {
[player play];
}];
}
else
{
// Re-bind the player when playing
controller.player = player;
}
}
@end
如果您将这段代码复制到您自己的应用程序中,或者自己尝试一下,您会发现调用 controller.player = nil
时,它会导致字幕在 AVPlayer
上停止工作。我发现修复它的唯一方法是删除 AVPlayer
对象并创建一个全新的 AVPlayer
来替换它。
是否有我遗漏的东西、我不知道的方法调用或我误解的东西?或者这只是一个 iOS 13 错误?
我找到了一个不太优雅的解决方案来解决这个问题!
当您调用controller.player = nil;
时,您还必须完全销毁AVPlayerViewController:[controller.view removeFromSuperview]; controller = nil;
然后当你想再次设置播放器时,你创建一个新的AVPlayerViewController。这会导致音频和视频中出现一个小插曲(大约 0.1 秒),但字幕会起作用!
根据 Apple 的文档,如果您想在后台播放视频的音频内容,则必须在移动应用程序时断开 AVPlayer
与其 AVPlayerViewController
或 AVPlayerLayer
的连接到后台以防止音频自动暂停:
我注意到在 iOS 13 中,这样做会导致隐藏式字幕中断。我创建了一个新项目(单视图应用程序)来为这个问题创建一个最小的重现案例。我的情节提要由一个视图和一个按钮组成,按钮作为一个动作连接到我的视图控制器 ("playPressed")。这是我的 ViewController.m
:
//
// ViewController.m
// AVPlayerViewControllerBug
//
// Created by Steven Barnett on 9/27/19.
// Copyright © 2019 BlueFrame Tech. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
{
@private
AVPlayerViewController *controller;
AVPlayer *player;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
controller = [[AVPlayerViewController alloc] init];
player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:@"https://vcloud.blueframetech.com/file/hls/143758.m3u8"]];
controller.player = player;
[player addObserver:self forKeyPath:@"rate" options:0 context:nil];
}
- (IBAction)playPressed:(id)sender {
[self presentViewController:controller animated:YES completion:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// Since we're ONLY observing "rate" on the player, assume
// that's what changed to call this
AVPlayer *player = (AVPlayer*)object;
if (player.rate == 0)
{
// Unbind the player from the view controller when paused
controller.player = nil;
// Since I haven't built custom controls for the player,
// when it's unbound there's no way to hit the play
// button. So we'll just start playing after a timer
// has elapsed
[NSTimer scheduledTimerWithTimeInterval:2.0 repeats:NO block:^(NSTimer * _Nonnull timer) {
[player play];
}];
}
else
{
// Re-bind the player when playing
controller.player = player;
}
}
@end
如果您将这段代码复制到您自己的应用程序中,或者自己尝试一下,您会发现调用 controller.player = nil
时,它会导致字幕在 AVPlayer
上停止工作。我发现修复它的唯一方法是删除 AVPlayer
对象并创建一个全新的 AVPlayer
来替换它。
是否有我遗漏的东西、我不知道的方法调用或我误解的东西?或者这只是一个 iOS 13 错误?
我找到了一个不太优雅的解决方案来解决这个问题!
当您调用controller.player = nil;
时,您还必须完全销毁AVPlayerViewController:[controller.view removeFromSuperview]; controller = nil;
然后当你想再次设置播放器时,你创建一个新的AVPlayerViewController。这会导致音频和视频中出现一个小插曲(大约 0.1 秒),但字幕会起作用!