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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:18:15