使用AndroidX Media3的Transformer API加工视频文件
Media3的Transformer API提供了一套强大的工具来对媒体文件进行处理、转换和增强。下面将详细介绍如何使用Transformer API来加工视频文件。
一、环境配置与基础概念
1. 添加Gradle依赖
dependencies {
// Transformer核心库
implementation 'androidx.media3:media3-transformer:1.1.1'
// 视频处理支持
implementation 'androidx.media3:media3-effect:1.1.1'
// GPU加速支持
implementation 'androidx.media3:media3-gl:1.1.1'
// 基础库
implementation 'androidx.media3:media3-common:1.1.1'
}
2. 添加权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 如果使用相机输入 -->
<uses-permission android:name="android.permission.CAMERA" />
3. Transformer核心概念
二、基础用法:转换视频格式
1. 简单格式转换(MP4转MP4)
public void convertVideoFormat(Context context, Uri inputUri, Uri outputUri) {
// 创建输入媒体项
MediaItem mediaItem = MediaItem.fromUri(inputUri);
// 创建Transformer
Transformer transformer = new Transformer.Builder(context)
.setOutputMimeType(MimeTypes.VIDEO_MP4) // 输出MP4格式
.build();
// 设置监听器
transformer.start(mediaItem, outputUri);
// 添加监听器(可选)
transformer.addListener(new Transformer.Listener() {
@Override
public void onCompleted(Composition composition, @Nullable TransformationResult result) {
Log.d("Transformer", "转换完成: " + outputUri);
}
@Override
public void onError(Composition composition, TransformationException e) {
Log.e("Transformer", "转换错误: " + e.getMessage());
}
});
}
2. 转换指定参数
public void convertWithParams(Context context, Uri inputUri, Uri outputUri) {
Transformer transformer = new Transformer.Builder(context)
.setOutputMimeType(MimeTypes.VIDEO_MP4)
.setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setEnableFallback(false) // 禁用备用编码器
.build())
.setVideoMimeEncoderSettings(
new VideoEncoderSettings.Builder()
.setBitrate(4000000) // 4Mbps
.setFrameRate(30)
.setWidth(1280)
.setHeight(720)
.build())
.setAudioMimeEncoderSettings(
new AudioEncoderSettings.Builder()
.setBitrate(128000) // 128kbps
.setSampleRate(44100)
.setChannelCount(2)
.build())
.build();
transformer.start(MediaItem.fromUri(inputUri), outputUri);
}
三、高级变换操作
1. 视频剪辑
public void trimVideo(Context context, Uri inputUri, Uri outputUri) {
// 剪辑从第5秒到第15秒的片段
long startMs = 5_000; // 5秒
long endMs = 15_000; // 15秒
MediaItem mediaItem = new MediaItem.Builder()
.setUri(inputUri)
.setClippingConfiguration(
new MediaItem.ClippingConfiguration.Builder()
.setStartPositionMs(startMs)
.setEndPositionMs(endMs)
.build())
.build();
new Transformer.Builder(context)
.build()
.start(mediaItem, outputUri);
}
2. 改变播放速度
public void changeVideoSpeed(Context context, Uri inputUri, Uri outputUri, float speedFactor) {
MediaItem mediaItem = new MediaItem.Builder()
.setUri(inputUri)
.build();
Composition composition = new Composition.Builder(
new EditedMediaItemSequence(
new EditedMediaItem.Builder(mediaItem)
.setEffects(
new Effects(
Collections.emptyList(),
Collections.singletonList(
new SpeedChangeProcessor(speedFactor))))
.build()))
.build();
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
3. 添加视频滤镜
public void applyVideoFilter(Context context, Uri inputUri, Uri outputUri) {
// 创建RGB调色滤镜
RgbAdjustment rgbAdjustment = new RgbAdjustment.Builder()
.setRedScale(1.2f) // 增加红色
.setGreenScale(0.9f) // 减少绿色
.setBlueScale(1.1f) // 增加蓝色
.build();
// 创建灰度滤镜
GrayscaleFilter grayscaleFilter = new GrayscaleFilter();
// 创建链式滤镜 - 先应用灰度,再应用调色
ScaleToFitTransformation scaleToFit = ScaleToFitTransformation.DEFAULT;
ImmutableList<Effect> videoEffects = new ImmutableList.Builder<Effect>()
.add(grayscaleFilter)
.add(rgbAdjustment)
.build();
MediaItem mediaItem = new MediaItem.Builder()
.setUri(inputUri)
.build();
EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem)
.setEffects(new Effects(videoEffects, Collections.emptyList()))
.build();
Composition composition = new Composition.Builder(
new EditedMediaItemSequence(editedMediaItem))
.build();
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
4. 添加水印
public void addWatermark(Context context, Uri inputUri, Uri outputUri, Bitmap watermarkBitmap) {
// 创建水印覆盖
OverlaySettings overlaySettings = new OverlaySettings.Builder()
.setAnchor(OverlaySettings.ANCHOR_TYPE_TOP | OverlaySettings.ANCHOR_TYPE_RIGHT)
.setHorizontalOffset(0.05f) // 5%边距
.setVerticalOffset(0.05f) // 5%边距
.setScale(0.2f) // 原始尺寸的20%
.build();
// 创建位图覆盖
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(
watermarkBitmap, overlaySettings);
// 创建叠加层效果
OverlayEffect overlayEffect = new OverlayEffect(Collections.singletonList(bitmapOverlay));
// 应用到视频
MediaItem mediaItem = new MediaItem.Builder()
.setUri(inputUri)
.build();
EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem)
.setEffects(new Effects(Collections.singletonList(overlayEffect), Collections.emptyList()))
.build();
Composition composition = new Composition.Builder(
new EditedMediaItemSequence(editedMediaItem))
.build();
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
四、视频合并与分割
1. 合并多个视频
public void mergeVideos(Context context, List<Uri> inputUris, Uri outputUri) {
List<Sequence> sequences = new ArrayList<>();
// 为每个输入文件创建一个序列
for (Uri uri : inputUris) {
MediaItem mediaItem = new MediaItem.Builder()
.setUri(uri)
.build();
sequences.add(new EditedMediaItemSequence(mediaItem));
}
// 添加背景音乐
MediaItem audioItem = new MediaItem.Builder()
.setUri("asset:///background_music.mp3")
.build();
Sequence audioSequence = new EditedMediaItemSequence(
new EditedMediaItem.Builder(audioItem).build());
sequences.add(audioSequence);
// 构建组合
Composition composition = new Composition.Builder(sequences)
.setEffects(
new Composition.Effects(Collections.singletonList(
// 混音设置:降低音频音量
new ChangeVolume(0.7f))))
.build();
// 执行转换
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
2. 分割视频(创建视频片段)
public void splitVideo(
Context context,
Uri inputUri,
File outputDir,
int segmentDurationSec
) {
MediaItem mediaItem = MediaItem.fromUri(inputUri);
for (int i = 0; ; i++) {
long startMs = i * segmentDurationSec * 1000L;
long endMs = startMs + segmentDurationSec * 1000L;
if (startMs >= mediaItem.clippingConfiguration.endPositionMs) {
break; // 超过视频长度
}
// 设置剪辑范围
MediaItem clippedItem = new MediaItem.Builder()
.setUri(inputUri)
.setClippingConfiguration(
new MediaItem.ClippingConfiguration.Builder()
.setStartPositionMs(startMs)
.setEndPositionMs(Math.min(endMs, mediaItem.clippingConfiguration.endPositionMs))
.build())
.build();
// 创建输出路径
Uri outputUri = Uri.fromFile(new File(outputDir, "segment_" + i + ".mp4"));
// 启动转换
new Transformer.Builder(context)
.build()
.start(clippedItem, outputUri);
}
}
五、复杂编辑组合
1. 创建画中画效果
public void pictureInPicture(
Context context,
Uri mainVideoUri,
Uri pipVideoUri,
Uri outputUri
) {
// 主视频轨道
EditedMediaItem mainItem = new EditedMediaItem.Builder(MediaItem.fromUri(mainVideoUri))
.setRemoveAudio(false)
.build();
// 画中画视频轨道
ScaleToFitTransformation pipTransformation = new ScaleToFitTransformation(
MatrixUtil.createScale(0.3f, 0.3f), // 缩放30%
MatrixUtil.createTranslation(0.7f, 0.7f)); // 位置
Effects pipEffects = new Effects(
Collections.singletonList(pipTransformation),
Collections.emptyList());
EditedMediaItem pipItem = new EditedMediaItem.Builder(MediaItem.fromUri(pipVideoUri))
.setEffects(pipEffects)
.setRemoveAudio(true) // 移除画中画音频
.build();
// 组合视频序列
Composition composition = new Composition.Builder(
new Sequence(mainItem),
new Sequence(pipItem))
.build();
// 执行转换
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
2. 添加片头片尾
public void addIntroOutro(
Context context,
Uri mainVideoUri,
Uri introUri,
Uri outroUri,
Uri outputUri
) {
// 创建片头
EditedMediaItem intro = new EditedMediaItem.Builder(MediaItem.fromUri(introUri))
.setRemoveAudio(false)
.build();
// 创建主视频
EditedMediaItem main = new EditedMediaItem.Builder(MediaItem.fromUri(mainVideoUri))
.setRemoveAudio(false)
.build();
// 创建片尾
EditedMediaItem outro = new EditedMediaItem.Builder(MediaItem.fromUri(outroUri))
.setRemoveAudio(false)
.build();
// 组合所有序列
Composition composition = new Composition.Builder(
new Sequence(intro),
new Sequence(main),
new Sequence(outro))
.build();
// 执行转换
new Transformer.Builder(context)
.build()
.start(composition, outputUri);
}
六、性能优化与高级配置
1. GPU加速处理
public void gpuAcceleratedTransform(Context context, Uri inputUri, Uri outputUri) {
Transformer transformer = new Transformer.Builder(context)
.setVideoEffects(
new Effects(
Collections.singletonList(new RgbAdjustment()), // GPU支持滤镜
Collections.emptyList()))
.setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setEnableSdrToneMapping(true) // 启用HDR转SDR
.build())
.setRendererFactory(
new TransformerUtil.createDefaultRendererFactory(context)
.setEnableDecoderFallback(true))
.build();
transformer.start(MediaItem.fromUri(inputUri), outputUri);
}
2. 内存优化策略
public void optimizedTransform(Context context, Uri inputUri, Uri outputUri) {
// 配置内存优化策略
DefaultAllocator allocator = new DefaultAllocator(true, 1024 * 1024); // 1MB块大小
LoadControl loadControl = new DefaultLoadControl.Builder()
.setAllocator(allocator)
.setBufferDurationsMs(3000, 5000, 1000, 2000)
.setPrioritizeTimeOverSizeThresholds(true)
.setTargetBufferBytes(C.LENGTH_UNSET)
.build();
// 创建转换器
Transformer transformer = new Transformer.Builder(context)
.setLoadControl(loadControl)
.setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setEnableAsyncQueueing(true) // 异步编码
.build())
.build();
transformer.start(MediaItem.fromUri(inputUri), outputUri);
}
3. 进度监控与取消
public void transformWithProgress(Context context, Uri inputUri, Uri outputUri) {
Transformer transformer = new Transformer.Builder(context)
.build();
UUID jobId = UUID.randomUUID();
TransformationRequest transformationRequest = new TransformationRequest.Builder()
.build();
transformer.start(MediaItem.fromUri(inputUri), outputUri);
// 添加进度监听器
transformer.addListener(new Transformer.Listener() {
@Override
public void onTransformationProgressed(Composition composition, TransformationResult result) {
float progress = (float) result.progress * 100;
Log.i("Transformer", "进度: " + progress + "%");
}
// ... 其他回调方法
});
// 取消示例
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (transformer.getState() == Transformer.STATE_STARTED) {
transformer.cancel();
Log.i("Transformer", "转换已取消");
}
}, 5000); // 5秒后取消
}
七、实战案例:创建视频处理管道
完整的视频处理流程
public void processVideoPipeline(Context context, Uri inputUri, Uri outputUri) {
// 1. 创建复杂效果组合
RgbAdjustment colorEffect = new RgbAdjustment.Builder()
.setRedScale(1.1f)
.setGreenScale(0.95f)
.setBlueScale(1.05f)
.build();
Bitmap watermark = BitmapFactory.decodeResource(context.getResources(), R.drawable.watermark);
BitmapOverlay watermarkOverlay = BitmapOverlay.createStaticBitmapOverlay(
watermark,
new OverlaySettings.Builder()
.setScale(0.15f)
.setAnchor(OverlaySettings.ANCHOR_TYPE_BOTTOM | OverlaySettings.ANCHOR_TYPE_RIGHT)
.setHorizontalOffset(0.05f)
.setVerticalOffset(0.05f)
.build());
OverlayEffect overlayEffect = new OverlayEffect(Collections.singletonList(watermarkOverlay));
// 2. 添加背景音乐
EditedMediaItem audioItem = new EditedMediaItem.Builder(
MediaItem.fromUri("asset:///background_music.mp3"))
.setEffects(new Effects(Collections.emptyList(),
Collections.singletonList(new ChangeVolume(0.5f))))
.build();
// 3. 配置视频源
EditedMediaItem videoItem = new EditedMediaItem.Builder(MediaItem.fromUri(inputUri))
.setEffects(new Effects(
Arrays.asList(colorEffect, overlayEffect),
Collections.emptyList()))
.build();
// 4. 添加片头片尾
EditedMediaItem introItem = new EditedMediaItem.Builder(
MediaItem.fromUri("asset:///intro.mp4"))
.build();
EditedMediaItem outroItem = new EditedMediaItem.Builder(
MediaItem.fromUri("asset:///outro.mp4"))
.build();
// 5. 创建时间线
Sequence introSequence = new Sequence(introItem);
Sequence videoSequence = new Sequence(videoItem);
Sequence outroSequence = new Sequence(outroItem);
Sequence audioSequence = new Sequence(audioItem);
// 6. 构建组合
Composition composition = new Composition.Builder(
introSequence,
videoSequence,
outroSequence,
audioSequence)
.setEffects(new Composition.Effects(
Collections.singletonList(new ScaleToFitTransformation())))
.setAudioMixingParameters(
new AudioMixingParameters.Builder()
.setVideoVolume(1.0f) // 主视频音量100%
.setAudioTrackVolume(0.5f, 0) // 音频轨道50% (第一个轨道)
.build())
.build();
// 7. 配置转换器
Transformer transformer = new Transformer.Builder(context)
.setOutputMimeType(MimeTypes.VIDEO_MP4)
.setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setEnableHdrEditing(true)
.build())
.setVideoEffects(
new Effects(
Collections.singletonList(new Contrast(1.2f)), // 整体增强对比度
Collections.emptyList()))
.build();
// 8. 开始处理
transformer.start(composition, outputUri);
}
八、常见问题解决
1. 错误处理与恢复
public void transformWithErrorHandling(Context context, Uri inputUri, Uri outputUri) {
Transformer transformer = new Transformer.Builder(context)
.build();
transformer.addListener(new Transformer.Listener() {
@Override
public void onError(Composition composition, TransformationException e) {
if (e.errorCode == TransformationException.ERROR_CODE_DECODING_FAILED) {
Log.e("Transformer", "解码失败,尝试软解...");
// 尝试软解
Transformer softDecoderTransformer = new Transformer.Builder(context)
.setDecoderFactory(
new DefaultDecoderFactory.Builder()
.setForceSoftwareRenderer(true)
.build())
.build();
softDecoderTransformer.start(composition, outputUri);
}
}
// ... 其他回调
});
transformer.start(MediaItem.fromUri(inputUri), outputUri);
}
2. 性能优化表
| 问题 | 优化方案 | 效果 |
|---|---|---|
| 卡顿严重 | 降低分辨率(720p->480p) | CPU降低40% |
| 处理速度慢 | 启用硬件编码器 | 速度提升3-5倍 |
| 内存占用高 | 设置帧缓冲区限制 | 内存减少50% |
| 输出文件大 | 降低码率(6Mbps->3Mbps) | 文件大小减半 |
| 手机发热 | 降低帧率(30fps->24fps) | 温度降低5°C |
3. 兼容性配置
public Transformer createCompatibleTransformer(Context context) {
return new Transformer.Builder(context)
.setEncoderFactory(
new DefaultEncoderFactory.Builder(context)
.setEnableFallback(true) // 支持备用编码器
.setEnableAsyncQueueing(true)
.build())
.setDecoderFactory(
new DefaultDecoderFactory.Builder()
.setForceSoftwareRenderer(false)
.setEnableFallback(true) // 支持备用解码器
.build())
.setRenderersFactory(
new DefaultRenderersFactory(context)
.setExtensionRendererMode(RendererCapabilities.EXTENSION_RENDERER_MODE_ON)
.build())
.build();
}
总结
通过Media3的Transformer API,您可以实现强大的视频处理功能:
- 基础转换:格式转换、参数调整
- 编辑功能:剪辑、合并、分割
- 效果处理:滤镜、水印、速度调节
- 高级组合:画中画、片头片尾添加
- 性能优化:硬件加速、内存控制
核心优势:
- 现代API:基于最新的AndroidX Media3库
- 强大效果:支持滤镜、变速、裁剪等复杂操作
- GPU加速:利用设备GPU提升处理速度
- 灵活组合:通过Composition组合多个媒体源
- 进度控制:实时监控与取消操作
最佳实践建议:
- 尽量使用硬件加速
- 对大文件分块处理
- 合理控制内存使用
- 添加进度反馈和错误处理
- 根据目标设备优化输出参数
Transformer API适用于多种场景:
- 社交媒体应用:视频预处理
- 内容创作工具:添加特效
- 视频编辑应用:拼接剪辑
- 企业应用:添加水印或LOGO
- 多媒体系统:格式转换
通过本指南,您应该能够构建高效的视频处理功能,满足各种视频加工需求。
2433

被折叠的 条评论
为什么被折叠?



