Swift实现MP4视频导出时修改帧率与码率的方法
修改MOV转MP4时的帧率与码率方案
要自定义导出MP4的帧率和码率,仅靠AVAssetExportSession的系统预设无法实现精细控制,需要改用AVAssetWriter手动配置编码参数。以下是替换后的完整实现:
func convertMOVtoMP4WithCustomParams(inputURL: URL, outputURL: URL, targetFrameRate: Int, targetBitRate: Int, completion: @escaping (Bool) -> Void) { let asset = AVURLAsset(url: inputURL) // 获取视频轨和音频轨 guard let videoTrack = asset.tracks(withMediaType: .video).first, let audioTrack = asset.tracks(withMediaType: .audio).first else { completion(false) return } // 初始化AVAssetWriter guard let writer = try? AVAssetWriter(outputURL: outputURL, fileType: .mp4) else { completion(false) return } // 配置视频输入参数 let videoSettings: [String: Any] = [ AVVideoCodecKey: AVVideoCodecType.h264, AVVideoWidthKey: videoTrack.naturalSize.width, AVVideoHeightKey: videoTrack.naturalSize.height, AVVideoAverageBitRateKey: targetBitRate, // 平均码率,单位bps AVVideoExpectedFrameRateKey: targetFrameRate, // 目标帧率 AVVideoCompressionPropertiesKey: [ AVVideoProfileLevelKey: AVVideoProfileLevelH264BaselineAutoLevel, AVVideoMaxKeyFrameIntervalKey: targetFrameRate * 2 // 关键帧间隔 ] ] let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings) videoInput.expectsMediaDataInRealTime = false videoInput.transform = videoTrack.preferredTransform // 配置音频输入参数 let audioSettings: [String: Any] = [ AVFormatIDKey: kAudioFormatMPEG4AAC, AVNumberOfChannelsKey: 2, AVSampleRateKey: 44100, AVEncoderBitRateKey: 128000 // 音频码率,128kbps ] let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioSettings) audioInput.expectsMediaDataInRealTime = false // 添加输入到writer if writer.canAdd(videoInput) { writer.add(videoInput) } if writer.canAdd(audioInput) { writer.add(audioInput) } // 开始写入 let reader = AVAssetReader(asset: asset)! let videoOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA]) let audioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: nil) if reader.canAdd(videoOutput) { reader.add(videoOutput) } if reader.canAdd(audioOutput) { reader.add(audioOutput) } writer.startWriting() writer.startSession(atSourceTime: .zero) reader.startReading() // 处理视频数据写入 videoInput.requestMediaDataWhenReady(on: DispatchQueue.global()) { while videoInput.isReadyForMoreMediaData { if let sampleBuffer = videoOutput.copyNextSampleBuffer() { videoInput.append(sampleBuffer) } else { videoInput.markAsFinished() break } } } // 处理音频数据写入 audioInput.requestMediaDataWhenReady(on: DispatchQueue.global()) { while audioInput.isReadyForMoreMediaData { if let sampleBuffer = audioOutput.copyNextSampleBuffer() { audioInput.append(sampleBuffer) } else { audioInput.markAsFinished() break } } } // 监听写入完成 writer.finishWriting { completion(writer.status == .completed) } }
关键参数说明
- 目标帧率:通过
AVVideoExpectedFrameRateKey设置,比如传入30就代表30帧每秒,可根据需求调整为24、60等数值。 - 目标码率:
AVVideoAverageBitRateKey控制视频平均码率,单位是bps(比特每秒),比如1000000代表1Mbps,数值越小视频体积越小,但画质会相应降低。 - 音频码率:音频部分的
AVEncoderBitRateKey可按需调整,128kbps是常见的平衡音质和体积的取值。
调用示例:
// 转成30帧、1Mbps码率的MP4 convertMOVtoMP4WithCustomParams( inputURL: movFileURL, outputURL: mp4FileURL, targetFrameRate: 30, targetBitRate: 1000000 ) { success in print(success ? "转换成功" : "转换失败") }
内容的提问来源于stack exchange,提问作者Wahab Khan Jadon
相关产品推荐
相关产品推荐

