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

Swift 5视频文件压缩求助:将相册视频转为低质量压缩视频

Swift Solution for Local Video Compression (Photo Library Input → Compressed URL Output)

Hey there! I totally feel your pain—this is such a common task, but finding modern, working Swift solutions can be surprisingly tough. Let’s build a reliable, up-to-date implementation using Apple’s native AVFoundation and Photos frameworks to handle video compression from the photo library.

Step 1: Set Up Photo Library Permissions

First, you need to request access to the user’s photo library. Add these keys to your Info.plist (right-click → Open As → Source Code) with a clear explanation for why you need access:

<key>NSPhotoLibraryUsageDescription</key>
<string>Need access to your videos to compress them</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Need access to save the compressed video back to your library (optional)</string>

Step 2: Fetch the Video URL from the Photo Library

Assuming you’ve already selected a PHAsset (video) from the photo library, use this code to get its local file URL:

import Photos

func getVideoURL(from asset: PHAsset, completion: @escaping (URL?) -> Void) {
    let options = PHVideoRequestOptions()
    options.isNetworkAccessAllowed = false // Only fetch local videos
    options.version = .original
    
    PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, _, error in
        guard let urlAsset = avAsset as? AVURLAsset, error == nil else {
            completion(nil)
            return
        }
        completion(urlAsset.url)
    }
}

Step 3: Core Video Compression Function

This function takes the input video URL, compresses it to a low-quality preset, and returns the URL of the compressed output file (stored in your app’s Documents directory):

import AVFoundation

func compressVideo(inputURL: URL, completion: @escaping (URL?, Error?) -> Void) {
    // Create a temporary output URL in the app's Documents folder
    let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let outputURL = documentsDir.appendingPathComponent("compressed_video_\(UUID().uuidString).mp4")
    
    guard let asset = AVAsset(url: inputURL) else {
        completion(nil, NSError(domain: "CompressionError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid video asset"]))
        return
    }
    
    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetLowQuality) else {
        completion(nil, NSError(domain: "CompressionError", code: -2, userInfo: [NSLocalizedDescriptionKey: "Failed to create export session"]))
        return
    }
    
    exportSession.outputURL = outputURL
    exportSession.outputFileType = .mp4
    exportSession.shouldOptimizeForNetworkUse = true // Helps with faster streaming/sharing
    
    exportSession.exportAsynchronously {
        switch exportSession.status {
        case .completed:
            completion(outputURL, nil)
        case .failed, .cancelled:
            completion(nil, exportSession.error ?? NSError(domain: "CompressionError", code: -3, userInfo: [NSLocalizedDescriptionKey: "Export failed or cancelled"]))
        default:
            break
        }
    }
}

Step 4: Putting It All Together

Here’s how to use the two functions above in your workflow (e.g., after selecting a video from the photo library):

// Example: Assume you have a selected PHAsset named 'selectedVideoAsset'
getVideoURL(from: selectedVideoAsset) { inputURL in
    guard let inputURL = inputURL else {
        print("Failed to get video URL from photo library")
        return
    }
    
    compressVideo(inputURL: inputURL) { outputURL, error in
        if let error = error {
            print("Compression failed: \(error.localizedDescription)")
            return
        }
        
        guard let compressedURL = outputURL else {
            print("No compressed video URL returned")
            return
        }
        
        // Use the compressedURL for your needs (upload, share, etc.)
        print("Compressed video ready at: \(compressedURL)")
        
        // Optional: Save the compressed video back to the photo library
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: compressedURL)
        }) { success, error in
            if success {
                print("Compressed video saved to photo library")
            } else if let error = error {
                print("Failed to save compressed video: \(error.localizedDescription)")
            }
        }
    }
}

Key Notes

  • Customization: If AVAssetExportPresetLowQuality isn’t low enough for your needs, you can create a custom export preset with lower bitrates using AVAssetWriter (it’s more code, but gives full control).
  • Cleanup: Remember to delete temporary compressed files from the Documents directory when you’re done with them to save storage space.
  • Background Handling: If you’re compressing large videos, consider wrapping the export task in a background session to avoid interruptions when the app is in the background.

This solution is fully Swift-based, uses Apple’s modern frameworks, and handles local photo library videos reliably—no outdated Obj-C hacks required.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 10:32:58