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

Xcode中模拟器与真机视频仅播音频无法显示问题求助

解决SwiftUI中AWS S3视频仅播放音频无画面的问题

核心问题分析

你遇到的问题主要源于两点:

  1. SwiftUI视图内直接创建AVPlayer会因视图刷新导致播放器重复初始化,生命周期混乱引发播放异常;
  2. 视频编码不兼容、S3元数据配置错误,或播放器初始化方式不当,触发AddInstanceForFactory插件注册错误。

以下是适配MVVM结构的解决方案:

1. 重构ViewModel管理AVPlayer

将播放器的创建、播放控制逻辑移至ViewModel,符合MVVM职责分离原则,同时避免视图刷新导致的播放器重复创建:

import AVKit

class ItemViewModel: ObservableObject {
    private(set) var player: AVPlayer?
    private let videoUrlString: String?
    
    init(item: LineItem) {
        self.videoUrlString = item.video
        setupPlayer()
    }
    
    private func setupPlayer() {
        guard let urlString = videoUrlString, let url = URL(string: urlString) else {
            return
        }
        let playerItem = AVPlayerItem(url: url)
        // 监听视频加载状态,排查加载失败问题
        playerItem.addObserver(self, forKeyPath: "status", options: [.new, .initial], context: nil)
        self.player = AVPlayer(playerItem: playerItem)
    }
    
    func play() {
        player?.play()
        player?.preventsDisplaySleepDuringVideoPlayback = true
    }
    
    func pause() {
        player?.pause()
    }
    
    // 处理状态监听,避免内存泄漏
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard keyPath == "status", let playerItem = object as? AVPlayerItem else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }
        
        switch playerItem.status {
        case .readyToPlay:
            break
        case .failed:
            print("视频加载失败:\(playerItem.error?.localizedDescription ?? "未知错误")")
        case .unknown:
            print("视频状态未知")
        @unknown default:
            break
        }
        playerItem.removeObserver(self, forKeyPath: "status")
    }
    
    deinit {
        player?.pause()
        player?.replaceCurrentItem(with: nil)
    }
}

2. 修改SwiftUI视图适配ViewModel

更新ItemRowView,通过StateObject持有ViewModel,统一控制播放生命周期:

import SwiftUI
import AVKit

struct ItemRowView: View {
    let item: LineItem
    @StateObject private var viewModel: ItemViewModel
    
    init(item: LineItem) {
        self.item = item
        self._viewModel = StateObject(wrappedValue: ItemViewModel(item: item))
    }
    
    var body: some View {
        ZStack {
            HStack {
                VStack {
                    Text(item.name)
                        .font(.title2)
                        .fontWeight(.bold)
                        .padding()
                    VStack {
                        if let player = viewModel.player {
                            VideoPlayer(player: player)
                                .onAppear() {
                                    viewModel.play()
                                }
                                .onDisappear {
                                    viewModel.pause()
                                }
                                .frame(height: 300) // 固定视频高度,避免布局异常
                        } else {
                            AsyncImage(url: URL(string: item.picture ?? "")) { image in
                                image.resizable()
                                    .scaledToFit()
                            } placeholder: {
                                ProgressView()
                            }
                            .transition(.opacity.combined(with: .scale))
                            Text(item.description)
                        }
                    }
                }
                .padding(.bottom)
            }
        }
    }
}

struct ItemRowView_Previews: PreviewProvider {
    static var previews: some View {
        ItemRowView(item: LineItem.testLineItems[1])
    }
}

3. 额外排查项

如果上述修改后仍有问题,检查以下内容:

  • 视频编码兼容性:确保S3中的视频使用iOS支持的编码(视频:H.264/MPEG-4 AVC,音频:AAC)。可通过ffmpeg -i 视频文件路径查看编码信息,不兼容则需转码。
  • S3元数据配置:在AWS S3控制台检查视频文件的Content-Type:mp4对应video/mp4,mov对应video/quicktime,配置错误会导致iOS无法识别视频格式。
  • S3访问权限:确保存储桶的CORS配置允许应用访问,或视频文件设置为公开可读(测试阶段可临时开启)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:25:22