尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

一篇文章吃透 ExoPlayer 视频转码:Transformer 离线编辑与导出的完整实战

一篇文章吃透 ExoPlayer 视频转码:Transformer 离线编辑与导出的完整实战 一篇文章吃透 ExoPlayer 视频转码Transformer 离线编辑与导出的完整实战【免费下载链接】ExoPlayerAn extensible media player for Android项目地址: https://gitcode.com/gh_mirrors/exop/ExoPlayer做了多年 Android 播放器最头疼的需求往往不是把视频播出来而是把视频改一改再交还用户——加个开场滤镜、去掉片尾几秒、把横屏改成竖屏、把两段素材拼成一个文件。原生 MediaCodec 管线又长又绕AVAsset 在 Android 上根本不存在很多团队被迫堆 FFmpeg 二进制。而 ExoPlayer 视频转码能力Transformer 模块把这条链路压缩到了几乎配置即所得的程度不用自己写编码循环、不用管理复用/释放缓冲只要描述我想对画面做什么剩下交给框架。读完本文你将掌握Transformer 离线转码与 Effect 渲染管线的前世今生依赖引入与官方 demo 的运行路径裁剪、旋转、缩放等几何变换的落地写法亮度、对比度、HSL、色彩 LUT 等调色效果的组合姿势多段视频拼接与导出进度监听的方法避免转码翻车的性能与调试清单先搞清楚一个前提为什么要用 Transformer 而不是实时滤镜实时滤镜demos/gl里的GlEffect链路处理的是播放中的每一帧画面直接送屏幕不落盘。而本文的主角 Transformer 是离线导出它读取输入源逐帧送入VideoFrameProcessor组成的处理链再交给DefaultEncoderFactory编码、DefaultMuxer封装最终写成一个新文件。一句话区分实时滤镜是看得见摸不着Transformer 视频转码是看得见、改得动、存得下。渲染架构见官方架构图它解释了视频帧在处理器之间流转的方式这张图来自 docs/glossary.md值得反复看。理解它的关键是记住三个名词组件职责Effect描述对帧做什么的抽象接口视频效果与音频处理器两大类VideoFrameProcessor帧处理器的执行引擎管理 OpenGL 纹理与线程Transformer导出编排器连接读取、处理、编码、封装四个环节环境准备依赖、demo、一条龙验证Transformer 位于独立模块library/transformer效果类在library/effect。在build.gradle中补齐依赖dependencies { implementation com.google.android.exoplayer:exoplayer-core:2.X.X implementation com.google.android.exoplayer:exoplayer-transformer:2.X.X implementation com.google.android.exoplayer:exoplayer-effect:2.X.X implementation com.google.android.exoplayer:exoplayer-ui:2.X.X }版本号请以项目根目录 RELEASENOTES.md 中的最新发布信息为准。如果你只是想先跑起来无需从零搭工程。项目自带一个完整的转码 demo代码在 demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/它会展示输入画面、实时显示导出进度、并在完成后回放输出文件。建议对照它阅读本文的每个示例——里面用到的PeriodicVignetteShaderProgram周期性暗角着色器正是自定义效果的现成范本。任务一让画面转起来——几何变换的最短路径先从一个最朴素的需求切入用户录了一段竖屏视频想顺时针转 90° 再横着看。在 Transformer 的世界里这不需要碰任何矩阵数学——直接使用现成的ScaleAndRotateTransformationScaleAndRotateTransformation rotation new ScaleAndRotateTransformation.Builder() .setRotationDegrees(90f) // 逆时针 90 度配合视频自带旋转可得到竖转横 .build();真正决定转完怎么摆放的是Presentation效果。它控制输出画幅与输入画面之间的适配策略对应测试资源里那些scale_to_fit、stretch_to_fit、crop的命名Presentation presentation new Presentation.Builder() .setWidth(1080) .setHeight(1920) .build(); // 默认走 scaleToFit可改为 setScaleToFitBehavior 精细控制下面两张测试帧是同一段素材在旋转后的效果对比第一张是原始帧第二张是旋转后的输出任务二给画面换气质——把调色玩出排列组合几何变换之外library/effect还内置了一整套颜色处理效果它们全部实现RgbMatrix或RgbFilter接口可以任意串联。下面是随手可用的几个效果类参数含义典型用途Brightness-1 ~ 10 为不变整体提亮/压暗Contrast0 ~ 21 为不变增强/减弱明暗反差HslAdjustment色调/饱和度/亮度三维氛围调色RgbAdjustment单通道偏移冷调/暖调偏色SingleColorLut颜色查找表复刻复古、赛博等风格以最常见的先提亮再降饱和为例两个效果按顺序塞进一个Effects容器即可Effects effects new Effects( /* audioProcessors */ ImmutableList.of(), /* videoEffects */ ImmutableList.of( new Brightness(0.1f), // 亮度加 0.1 new HslAdjustment.Builder() .adjustSaturation(-0.3f) // 饱和度下调 30% .build())); EditedMediaItem item new EditedMediaItem.Builder(mediaItem) .setEffects(effects) .build();效果列表的执行顺序就是渲染管线的串联顺序谁在前谁先生效。对比一下测试素材里灰度化前后的效果能直观看到单帧处理的威力任务三进阶玩法——画中画、贴纸与文字叠加如果你觉得调色不过瘾OverlayEffect才是重头戏。它允许把BitmapOverlay位图、DrawableOverlayDrawable 资源、TextureOverlay纹理甚至TextOverlay文字叠加到视频之上还能通过OverlaySettings精确控制位置、缩放与透明度——这正是贴纸/水印/片头字类功能的通用底座。OverlayEffect overlayEffect new OverlayEffect( ImmutableList.of( new BitmapOverlay(bitmapLoader, bitmapUri), new TextOverlay(EXOPLAYER, textStyle))); Effects effects new Effects( /* audioProcessors */ ImmutableList.of(), /* videoEffects */ ImmutableList.of( new Presentation.Builder().setWidth(1080).setHeight(1920).build(), overlayEffect));位图需要异步加载BitmapOverlay接受一个BitmapLoader负责把 URI 变成Bitmapdemo 里用的是DataSourceBitmapLoader可参照 demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java 的组装方式。叠加了默认文字水印的帧长这样任务四拼盘输出——多段视频合成一个文件现在把前面所有能力串起来完成多段素材 各自特效 导出成一个 MP4的完整闭环。Composition是导出的顶层描述一个EditedMediaItemSequence是顺序播放的一组素材多个 sequence 时间重叠的部分会做混流每个素材又可以挂独立的Effects。EditedMediaItemSequence sequence new EditedMediaItemSequence( ImmutableList.of( new EditedMediaItem.Builder(firstItem) .setEffects(openingEffects) // 开场滤镜 .build(), new EditedMediaItem.Builder(secondItem) .setRemoveAudio(true) // 第二段静音 .build())); Composition composition new Composition.Builder(ImmutableList.of(sequence)) .setEffects(compositionWideEffects) // 作用于整段的全局效果 .build();随后创建Transformer实例注册监听器并启动导出。导出是异步的进度通过ProgressHolder轮询获取Transformer transformer new Transformer.Builder(context) .addListener(new Transformer.Listener() { Override public void onCompleted(Composition composition, ExportResult exportResult) { // 导出成功result 中包含时长、编解码耗时等统计 } Override public void onError( Composition composition, ExportResult exportResult, ExportException error) { // 导出失败根据 error.errorCode 分类处理 } }) .build(); ProgressHolder progressHolder new ProgressHolder(); transformer.start(composition, outputFilePath); // 轮询进度transformer.getProgress(progressHolder) // 返回 PROGRESS_STATE_AVAILABLE 时读 progressHolder.progress核心就两条 APIstart(Composition, String)开干getProgress(ProgressHolder)看进度cancel()随时叫停。官方对导出生命周期、错误码、TransformationRequest的详细约定见 docs/transforming-media.md。性能优化与常见翻车点离线转码是重活几个高频问题提前给你排雷分辨率匹配输出分辨率应尽量贴近源分辨率避免无谓的缩放上采样Presentation的scaleToFit策略默认会等比适配别随手设一个与源相差过大的尺寸。音频处理器别乱挂Effects的audioProcessors列表只接收AudioProcessor如SonicAudioProcessor变速、SilenceSkippingAudioProcessor去静音误把视频效果塞进去会在构建阶段直接抛异常。HDR 输入要交代部分效果如Brightness明确不支持 HDR遇到 HDR 素材会校验失败。传参前先确认源格式必要时走 tone mapping 转 SDR。线程模型Transformer实例必须由单一应用线程访问绝大多数场景就是主线程跨线程操作会触发非法状态异常。看日志导出阶段的关键节点会输出ExoPlayerImplInternal/DefaultVideoFrameProcessor等模块日志配合 docs/debug-logging.md 里LogcatLogger的接法能快速定位是哪一环卡住。真机验证编码能力不同设备支持的编码器参数不同TransformationRequest中声明的目标参数可能被降级onFallbackApplied回调会告诉你实际用了什么。总结与下一步回顾这条从播放到转码的能力升级路径你已经拿到了三个关键认知Transformer 视频转码的核心是描述意图而非手写管线Effect接口是几何、调色、叠加三大类效果的统一入口Composition把单素材编辑升级为多段拼接与混流。测试素材下积累了数百张首帧截图见testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/任何自定义效果都能用它快速肉眼验证。如果想更进一步建议按这个顺序深入自定义GlEffect/GlShaderProgram参考 demos/transformer/src/main/assets/ 下的 GLSL 模板与PeriodicVignetteShaderProgram的实现写出你自己的风格化效果吃透TransformationRequest掌握视频/音频 MIME、码率、帧率的精细控制研究 demo 的矩阵工厂MatrixTransformationFactory.java 展示了如何用MatrixTransformation实现更自由的视角变换。如果这篇 ExoPlayer 视频转码实战对你有帮助点赞收藏支持一下。下一期我们聊聊如何把 Transformer 的导出管线与demos/gl的实时滤镜链路打通让预览即导出、所见即所得敬请期待。【免费下载链接】ExoPlayerAn extensible media player for Android项目地址: https://gitcode.com/gh_mirrors/exop/ExoPlayer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表