tvOS:无论如何要在 AVPlayer 之外显示字幕?

tvOS: Anyway to display a subtitle outside of the AVPlayer?

所以场景是有一个视图,用户可以在我帮助开发的应用程序中 enable/disable 字幕。

在那个视图上有一个示例文本 "This is what captions look like",目前它只是一个基本的、无样式的 UILabel。理想情况下,我希望它的样式与用户在系统设置中自定义字幕的方式类似。

这有可能吗?我设想了两种可能的方法:

  1. 创建一个 AVPlayer 实例和一个带有文本的 .vtt 文件,将其加载到视图中并暂停播放器。我不确定示例视频是否可行(并且它必须是透明的,因为示例子文本后面有图像)。

  2. 以某种方式获取用户为其字幕设置的所有样式(字体、大小、背景颜色等),并创建一个属性字符串来匹配

方法2似乎是最可行的方法,但我不知道我们是否可以在代码中访问这些设置。

所以我想通了!它基本上结合了 Media Accessibility API,它允许您获取用户为其 captions/subtitle 设置选择的值、属性字符串和子类 UILabel(尽管这可能 也许 被替换为 UITextView 因为这将允许您将其设置为 UIEdgeInsets 本机)

所以,首先,子类是允许插入UILabel。这是因为字幕可以有背景颜色和文本高亮颜色,如果没有插图,你只能看到文本高亮。所以子类的功能很简单:

class InsetUILabel: UILabel {
    override func drawTextInRect(rect: CGRect) {
        let inset: CGFloat = 15
        let insets: UIEdgeInsets = UIEdgeInsets(top: inset, left: inset/2, bottom: inset, right: inset/2)
        super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
    }
}

并用于生成实际标签。这使用了一个名为 textSample 的标签,但您显然可以使它更通用一些。

import MediaAccessibility

func styleLabel(sampleText: String) {
    let domain = MACaptionAppearanceDomain.User

    // Background styling
    let backgroundColor = UIColor(CGColor: MACaptionAppearanceCopyWindowColor(domain, nil).takeRetainedValue())
    let backgroundOpacity = MACaptionAppearanceGetWindowOpacity(domain, nil)
    textSample.layer.backgroundColor = backgroundColor.colorWithAlphaComponent(backgroundOpacity).CGColor
    textSample.layer.cornerRadius = MACaptionAppearanceGetWindowRoundedCornerRadius(domain, nil)

    // Text styling
    var textAttributes = [String:AnyObject]()
    let fontDescriptor = MACaptionAppearanceCopyFontDescriptorForStyle(domain, nil, MACaptionAppearanceFontStyle.Default).takeRetainedValue()
    let fontName = CTFontDescriptorCopyAttribute(fontDescriptor, "NSFontNameAttribute") as! String
    let fontColor = UIColor(CGColor: MACaptionAppearanceCopyForegroundColor(domain, nil).takeRetainedValue())
    let fontOpacity = MACaptionAppearanceGetForegroundOpacity(domain, nil)
    let textEdgeStyle = MACaptionAppearanceGetTextEdgeStyle(domain, nil)
    let textHighlightColor = UIColor(CGColor: MACaptionAppearanceCopyBackgroundColor(domain, nil).takeRetainedValue())
    let textHighlightOpacity = MACaptionAppearanceGetBackgroundOpacity(domain, nil)
    let textEdgeShadow = NSShadow()
    textEdgeShadow.shadowColor = UIColor.blackColor()
    let shortShadowOffset: CGFloat = 1.5
    let shadowOffset: CGFloat = 3.5

    switch(textEdgeStyle) {
    case .None:
        textEdgeShadow.shadowColor = UIColor.clearColor()

    case .DropShadow:
        textEdgeShadow.shadowOffset = CGSize(width: -shortShadowOffset, height: shortShadowOffset)
        textEdgeShadow.shadowBlurRadius = 6

    case .Raised:
        textEdgeShadow.shadowOffset = CGSize(width: 0, height: shadowOffset)
        textEdgeShadow.shadowBlurRadius = 5

    case .Depressed:
        textEdgeShadow.shadowOffset = CGSize(width: 0, height: -shadowOffset)
        textEdgeShadow.shadowBlurRadius = 5

    case .Uniform:
        textEdgeShadow.shadowColor = UIColor.clearColor()
        textAttributes[NSStrokeColorAttributeName] = UIColor.blackColor()
        textAttributes[NSStrokeWidthAttributeName] = -2.0

    default:
        break
    }

    textAttributes[NSFontAttributeName] = UIFont(name: fontName, size: (textSample.font?.pointSize)!)
    textAttributes[NSForegroundColorAttributeName] = fontColor.colorWithAlphaComponent(fontOpacity)
    textAttributes[NSShadowAttributeName] = textEdgeShadow
    textAttributes[NSBackgroundColorAttributeName] = textHighlightColor.colorWithAlphaComponent(textHighlightOpacity)

    textSample.attributedText = NSAttributedString(string: sampleText, attributes: textAttributes)
}

现在文本高亮部分使用了阴影,我认为这些值看起来很不错,但您可能需要稍微调整一下。希望这对您有所帮助!