iOS端使用Swift将.mov/.mp4导出为HTTP Live Streaming(HLS)文件
在iPhone上用Swift本地生成HLS流文件(TS/fMP4 + M3U8清单)
在iOS本地完成HLS流生成无需依赖后端服务,核心依赖AVFoundation框架即可实现视频分片与M3U8清单生成。以下是具体实现方案:
1. 基础准备
确保项目导入AVFoundation框架,并获取必要权限:
- 本地视频读取权限(如相册访问权限)
- 沙盒文件写入权限(默认已具备,如需存储到共享目录需额外配置)
2. 核心实现步骤
2.1 加载源视频资源
从本地文件路径创建AVURLAsset,支持.mov/.mp4格式:
import AVFoundation func loadSourceVideo(from url: URL) { let asset = AVURLAsset(url: url) // 预加载媒体轨道信息,避免后续导出等待 asset.loadValuesAsynchronously(forKeys: ["tracks"]) { var error: NSError? let status = asset.statusOfValue(forKey: "tracks", error: &error) if status == .loaded { DispatchQueue.main.async { self.exportHLS(from: asset) } } else { print("视频资源加载失败:\(error?.localizedDescription ?? "未知错误")") } } }
2.2 配置HLS导出参数
使用AVAssetExportSession配置导出规则,可指定分片格式、时长、输出目录等:
func exportHLS(from asset: AVURLAsset) { // 创建沙盒内的HLS输出目录(Documents下的HLSExport文件夹) guard let outputDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("HLSExport", isDirectory: true) else { print("输出目录创建失败") return } do { try FileManager.default.createDirectory(at: outputDir, withIntermediateDirectories: true) } catch { print("目录创建出错:\(error.localizedDescription)") return } // 输出的M3U8主清单路径 let outputPlaylistURL = outputDir.appendingPathComponent("stream.m3u8") // 初始化导出会话,指定画质预设 guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else { print("导出会话初始化失败") return } // 配置HLS输出参数 var outputSettings: [String: Any] = [:] // 选择分片格式:TS格式用AVFileType.hls,fMP4用AVFileType.hlsWithFragmentedMP4 outputSettings[AVFileTypeKey] = AVFileType.hls.rawValue // 替换为AVFileType.hlsWithFragmentedMP4.rawValue可生成fMP4分片 // 设置分片时长(单位:秒,建议5-15秒区间) outputSettings[AVAssetExportSessionHLSFragmentDurationKey] = 10 // 单码率场景下无需生成主清单,多码率场景设为true outputSettings[AVAssetExportSessionHLSGenerateMasterPlaylistKey] = false exportSession.outputURL = outputPlaylistURL exportSession.outputSettings = outputSettings exportSession.shouldOptimizeForNetworkUse = true // 优化分片的网络传输特性 // 执行导出 exportSession.exportAsynchronously { switch exportSession.status { case .completed: print("HLS导出完成!文件目录:\(outputDir.path)") // 此处可添加批量上传所有文件到服务器的逻辑 case .failed: print("导出失败:\(exportSession.error?.localizedDescription ?? "未知错误")") case .cancelled: print("导出被取消") default: break } } }
3. 关键参数说明
- 分片格式切换:
- TS分片:
AVFileTypeKey设为AVFileType.hls.rawValue,生成.ts后缀分片文件 - fMP4分片:设为
AVFileType.hlsWithFragmentedMP4.rawValue,生成.m4s后缀分片文件
- TS分片:
- 分片时长:通过
AVAssetExportSessionHLSFragmentDurationKey设置,需根据视频内容和网络场景调整 - 输出目录结构:导出完成后,目录内包含主M3U8清单、所有分片文件,多码率场景还会生成对应子清单与码率分片
4. 注意事项
- 导出操作建议在后台线程执行,避免阻塞UI;可配合
UIProgressView展示进度 - 若源视频编码为AV1等AVFoundation不支持的格式,需先转码为H.264/H.265再执行HLS导出
- 上传服务器时需将目录内所有文件完整上传,确保M3U8清单能正确关联分片文件
内容的提问来源于stack exchange,提问作者Micro
相关产品推荐
相关产品推荐

