Commit 4b30afcf by tanghuan

ios 使用 videotoolbox

1 parent 2d28f8c5
......@@ -24,14 +24,24 @@ class VideoUtil {
final fileSize = await File(inputPath).length();
String cmd;
if (Platform.isIOS && !_isIos18_6()) {
if (Platform.isIOS /*&& !_isIos18_6()*/) {
final bitrate = _getBitrateByFileSize(fileSize);
// cmd = '-i "$inputPath" '
// '-c:v h264_videotoolbox ' // 启用 iOS 硬件加速
// '-b:v ${bitrate}k ' // 根据文件大小自动计算码率
// '-vf scale=1280:-2 ' // 缩放到 720p (保持比例)
// '-c:a aac ' // 音频转为 AAC (兼容性最好)
// '-b:a 128k ' // 音频码率
// '"$outputPath"';
cmd = '-i "$inputPath" '
'-c:v h264_videotoolbox ' // 启用 iOS 硬件加速
'-b:v ${bitrate}k ' // 根据文件大小自动计算码率
'-vf scale=1280:-2 ' // 缩放到 720p (保持比例)
'-c:a aac ' // 音频转为 AAC (兼容性最好)
'-b:a 128k ' // 音频码率
'-c:v h264_videotoolbox '
'-b:v ${bitrate}k '
'-profile:v high ' // 确保使用高压缩率 Profile
'-vf "scale=trunc(oh*a/2)*2:720,format=yuv420p" ' // 强制 720p 且确保像素格式为 yuv420p
'-c:a aac '
'-b:a 128k '
'-movflags +faststart ' // 关键:优化 MP4 结构,支持边下边播
'-y ' // 自动覆盖已存在文件
'"$outputPath"';
} else {
final crf = _getCrfByFileSize(fileSize);
......@@ -72,7 +82,10 @@ class VideoUtil {
///
/// 通过 ffmpeg 压缩视频
/// [quality] 压缩质量,可选值: 'low' | 'middle' | 'high'
/// 未指定时根据文件大小自动计算CRF:文件越大压缩率越高,文件越小清晰度越高
/// 未指定时根据文件大小自动计算压缩参数:文件越大压缩率越高,文件越小清晰度越高
/// iOS 18.6.x: libx264 + CRF(h264_videotoolbox在iOS 18.6.x存在稳定性问题)
/// 其它iOS版本: h264_videotoolbox 硬件加速 + 码率控制
/// Android: libx264 + CRF
/// [onProgress] 进度回调,值范围 0.0 ~ 1.0
///
static Future<bool> compressVideo(
......@@ -83,40 +96,82 @@ class VideoUtil {
}) async {
final duration = await _getVideoDuration(inputPath);
// 使用CRF模式进行压缩,值范围0-51,建议值18-28
// 高质量: CRF 18-20
// 中等质量: CRF 23-26
// 低质量: CRF 28-32
int crf;
if (quality != null && quality.isNotEmpty) {
switch (quality) {
case 'low':
crf = 32;
break;
case 'middle':
crf = 26;
break;
case 'high':
crf = 20;
break;
default:
throw Exception('参数错误');
String cmd;
if (Platform.isIOS /*&& !_isIos18_6()*/) {
// iOS(非18.6+): 使用 h264_videotoolbox 硬件加速
// h264_videotoolbox 不支持 CRF,使用码率控制质量
int bitrate;
if (quality != null && quality.isNotEmpty) {
switch (quality) {
case 'low':
bitrate = 1500;
break;
case 'middle':
bitrate = 2500;
break;
case 'high':
bitrate = 4000;
break;
default:
throw Exception('参数错误');
}
} else {
final fileSize = await File(inputPath).length();
bitrate = _getBitrateByFileSize(fileSize);
}
// cmd = '-i "$inputPath" ' // 输入文件
// '-c:v h264_videotoolbox ' // iOS硬件加速视频编码器
// '-b:v ${bitrate}k ' // 根据质量/文件大小自动计算码率
// '-c:a aac ' // 音频编码器
// '-b:a 128k ' // 音频码率
// '-movflags faststart ' // 优化MP4文件结构
// '"$outputPath"'; // 输出文件
cmd = '-i "$inputPath" '
'-c:v h264_videotoolbox '
'-b:v ${bitrate}k '
'-profile:v high ' // 使用高配置以获得更好画质
'-pix_fmt yuv420p ' // 确保像素格式兼容性
'-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" ' // 强制偶数分辨率,防止报错
'-c:a aac '
'-b:a 128k '
'-movflags +faststart ' // 允许边下边播
'"$outputPath"';
} else {
// 根据文件大小自动计算CRF
final fileSize = await File(inputPath).length();
crf = _getCrfByFileSize(fileSize);
// iOS 18.6+ / Android: 使用 libx264 软件编码
// 使用CRF模式进行压缩,值范围0-51,建议值18-28
// 高质量: CRF 18-20
// 中等质量: CRF 23-26
// 低质量: CRF 28-32
int crf;
if (quality != null && quality.isNotEmpty) {
switch (quality) {
case 'low':
crf = 32;
break;
case 'middle':
crf = 26;
break;
case 'high':
crf = 20;
break;
default:
throw Exception('参数错误');
}
} else {
final fileSize = await File(inputPath).length();
crf = _getCrfByFileSize(fileSize);
}
cmd = '-i "$inputPath" ' // 输入文件
'-c:v libx264 ' // 视频编码器
'-crf $crf ' // 恒定速率因子(质量控制)
'-c:a aac ' // 音频编码器
'-b:a 128k ' // 音频比特率
// '-preset medium ' // 编码预设
'-preset fast ' // 编码预设,编码速度显著提升,体积损失很小
'-threads 0 ' // 让 libx264 自动使用所有可用 CPU 核心,默认行为可能只用单核
'-movflags faststart ' // 优化MP4文件结构
'"$outputPath"'; // 输出文件
}
String cmd = '-i "$inputPath" ' // 输入文件
'-c:v libx264 ' // 视频编码器
'-crf $crf ' // 恒定速率因子(质量控制)
'-c:a aac ' // 音频编码器
'-b:a 128k ' // 音频比特率
// '-preset medium ' // 编码预设
'-preset fast ' // 编码预设,编码速度显著提升,体积损失很小
'-threads 0 ' // 让 libx264 自动使用所有可用 CPU 核心,默认行为可能只用单核
'-movflags faststart ' // 优化MP4文件结构
'"$outputPath"'; // 输出文件
final completer = Completer<bool>();
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!