You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS16添加翻转图层后AVPlayer播放按钮不显示问题求解

AVPlayer视频翻转导致控制按钮不显示问题修复

问题现象

  • 应用内使用AVPlayer播放单份本地mp4视频,不同业务场景需要对同一份视频做水平翻转
  • iOS16系统下异常:播放/暂停、15秒快进/快退等控制按钮功能完全正常,可以正常点击触发,但按钮完全不显示,对应示意图第4项效果
  • 原有实现逻辑是在弹出AVPlayerViewController后,手动新建一个做了翻转变换的AVPlayerLayer盖在控制器视图上,这个额外添加的图层直接遮挡了iOS16新布局下的播放控制层。

问题效果示意图

原有问题代码

@IBAction func pressButton(_ sender: Any) {
    guard let path = Bundle.main.path(forResource: "sample-5s", ofType:"mp4") else {
       return
    }
    let avPlayer = AVPlayer(url: URL(fileURLWithPath: path))
    let avPlayerController = AVPlayerViewController()
    
    present(avPlayerController, animated: true, completion: {
      // 问题根源:额外新增AVPlayerLayer盖在控制器最上层,遮挡控制UI
      let flippedLayer = AVPlayerLayer(player: avPlayer)
      let transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
      flippedLayer.frame = (avPlayerController as UIViewController).view.frame
      flippedLayer.setAffineTransform(transform)
      (avPlayerController as UIViewController).view.layer.addSublayer(flippedLayer)
     
      avPlayerController.player = avPlayer
      avPlayer.play()
    })
  }

最优修复方案

不要手动新增AVPlayerLayer覆盖在AVPlayerViewController视图上,直接将翻转逻辑作用在视频渲染本身,完全不触碰系统控制层,兼容iOS15、iOS16及以上所有系统版本,也不需要强制切回iOS15的旧布局。

方案1:通过AVVideoComposition实现视频翻转(推荐)

翻转逻辑直接作用在视频资源的渲染流程中,不会对系统控制UI产生任何遮挡,性能最优,是官方推荐的视频变换实现方式:

@IBAction func pressButton(_ sender: Any) {
    guard let path = Bundle.main.path(forResource: "sample-5s", ofType:"mp4") else {
        return
    }
    let videoURL = URL(fileURLWithPath: path)
    let asset = AVAsset(url: videoURL)
    guard let videoTrack = asset.tracks(withMediaType: .video).first else { return }
    let playerItem = AVPlayerItem(asset: asset)
    
    // 配置水平翻转的视频合成规则
    let videoComposition = AVMutableVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in
        let source = request.sourceImage
        // 水平翻转:x轴缩放-1后平移对应宽度,适配CoreImage坐标系
        let flippedTransform = CGAffineTransform(scaleX: -1, y: 1).translatedBy(x: -source.extent.width, y: 0)
        let flippedImage = source.transformed(by: flippedTransform)
        request.finish(with: flippedImage, context: nil)
    })
    videoComposition.renderSize = videoTrack.naturalSize
    playerItem.videoComposition = videoComposition

    let avPlayer = AVPlayer(playerItem: playerItem)
    let avPlayerController = AVPlayerViewController()
    avPlayerController.player = avPlayer
    
    present(avPlayerController, animated: true) {
        avPlayer.play()
    }
}

关于保留iOS15播放布局的说明

iOS16对AVPlayerViewController的控制层UI做了系统级迭代,苹果没有提供任何公开API可以强制切换回iOS15的旧控制布局。不要尝试通过遍历子视图修改层级、hook系统方法的方式强行修改控制层样式,这类操作极容易在后续系统版本出现兼容崩溃,也有概率在App Store审核时被拒。

注意事项

  • 不要手动给AVPlayerViewController新增AVPlayerLayer,控制器内部会自动创建视频渲染图层,额外添加的图层不仅会遮挡UI,还会造成双倍的视频渲染性能损耗
  • 所有视频本身的变换(翻转、旋转、裁剪、加滤镜)优先通过AVVideoComposition实现,稳定性和兼容性远高于手动调整图层
  • 不要随意修改AVPlayerViewController的内部子视图层级,苹果会在不同系统版本调整内部视图结构,手动修改层级的适配成本极高

内容的提问来源于stack exchange,提问作者Luciano Perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 01:45:43