Xcode中模拟器与真机视频仅播音频无法显示问题求助
解决SwiftUI中AWS S3视频仅播放音频无画面的问题
核心问题分析
你遇到的问题主要源于两点:
- SwiftUI视图内直接创建
AVPlayer会因视图刷新导致播放器重复初始化,生命周期混乱引发播放异常; - 视频编码不兼容、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
相关产品推荐
相关产品推荐

