将 AVPlayerViewController.player 设置为 nil 会中断隐藏式字幕

Posted

技术标签:

【中文标题】将 AVPlayerViewController.player 设置为 nil 会中断隐藏式字幕【英文标题】:Setting AVPlayerViewController.player to nil breaks closed captions 【发布时间】:2019-09-27 18:44:40 【问题描述】:

根据 Apple 的文档,当您想在后台播放视频的音频内容时,您必须在将应用程序移至后台时断开 AVPlayer 与其 AVPlayerViewControllerAVPlayerLayer 的连接,以防止自动暂停的音频:

https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/creating_a_basic_video_player_ios_and_tvos/playing_audio_from_a_video_asset_in_the_background

我注意到在 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 的一个错误?

【问题讨论】:

【参考方案1】:

我找到了一个不太优雅的解决方案来解决这个问题!

当您调用controller.player = nil; 时,您还必须完全销毁 AVPlayerViewController[controller.view removeFromSuperview]; controller = nil;

然后当你想再次设置播放器时,你创建一个新的 AVPlayerViewController。这会在音频和视频中造成短暂的变化(大约 0.1 秒),但字幕会起作用!

【讨论】:

以上是关于将 AVPlayerViewController.player 设置为 nil 会中断隐藏式字幕的主要内容,如果未能解决你的问题,请参考以下文章

Swift/AppleTV4:如何将 AVPlayer 功能连接到 AVPlayerViewController?

将 AVPlayerViewController.player 设置为 nil 会中断隐藏式字幕

iOS 8 - 关闭全屏 AVPlayerViewController 时将方向更改回纵向

tvOS 中的 AVPlayerViewController 下拉菜单

在 AVPlayerViewController 全屏视图上呈现 UIView

更改 AVPlayerViewController 的播放控制按钮的颜色