SwiftUI中如何将视频URL显示为视频缩略图?
问题分析与解决方案
你当前使用的URLImageView仅支持加载图片资源,而视频URL本身并非图片文件,因此只会显示占位图。要实现视频缩略图展示,需要从视频资源中提取帧画面作为图片显示,可借助AVFoundation框架完成这一操作。
1. 实现视频缩略图视图
创建一个自定义View,负责从视频URL生成第一帧缩略图:
import SwiftUI import AVFoundation struct VideoThumbnailView: View { let videoURL: URL? let placeholder: String let width: CGFloat let height: CGFloat @State private var thumbnailImage: UIImage? var body: some View { Group { if let image = thumbnailImage { Image(uiImage: image) .resizable() .scaledToFill() } else { Image(placeholder) .resizable() .scaledToFill() } } .frame(width: width, height: height) .onAppear { guard let url = videoURL else { return } generateThumbnail(from: url) } } private func generateThumbnail(from url: URL) { let asset = AVAsset(url: url) let imageGenerator = AVAssetImageGenerator(asset: asset) imageGenerator.appliesPreferredTrackTransform = true // 保持视频原始方向 do { let cgImage = try imageGenerator.copyCGImage(at: .zero, actualTime: nil) self.thumbnailImage = UIImage(cgImage: cgImage) } catch { print("生成缩略图失败: \(error.localizedDescription)") } } }
2. 替换原视图代码
将原代码中的URLImageView替换为上述自定义视图:
struct GalleryVedioDetailsView: View { @State private var gotoPreview = false @StateObject private var viewModel = GalleryViewModel() var body: some View { ZStack { Color.hexF4F4FC .ignoresSafeArea() VStack(spacing: 0) { VStack { ScrollView { LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 4), count: 4), spacing: 4) { ForEach(0..<viewModel.video.count, id: \.self) { ind in Button { gotoPreview = true } label: { let width = ((screenWidth - 24) / 4) - 2 VideoThumbnailView( videoURL: URL(string: viewModel.video[ind].url ?? ""), placeholder: "PhotogalleryPlaceholder", width: width, height: width ) .scaledToFill() .clipped() } .buttonStyle(.plain) } } .padding(.top, 10) .padding(.horizontal, 12) } } } } } }
注意事项
- 确保App已开启网络权限(针对远程视频URL);本地视频直接传入本地文件URL即可。
- 若需优化性能,可添加缩略图缓存逻辑,避免重复生成;也可将缩略图生成逻辑移至ViewModel中异步处理。
- 若视频URL格式不合法或视频无法访问,仍会显示占位图,需在业务逻辑中增加URL有效性校验。
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

