碼:Transformer 離線編輯與導出的完整實戰(zhàn))
一篇文章吃透 ExoPlayer 視頻轉(zhuǎn)碼Transformer 離線編輯與導出的完整實戰(zhàn)【免費下載鏈接】ExoPlayerAn extensible media player for Android項目地址: https://gitcode.com/gh_mirrors/exop/ExoPlayer做了多年 Android 播放器最頭疼的需求往往不是把視頻播出來而是把視頻改一改再交還用戶——加個開場濾鏡、去掉片尾幾秒、把橫屏改成豎屏、把兩段素材拼成一個文件。原生 MediaCodec 管線又長又繞AVAsset 在 Android 上根本不存在很多團隊被迫堆 FFmpeg 二進制。而 ExoPlayer 視頻轉(zhuǎn)碼能力Transformer 模塊把這條鏈路壓縮到了幾乎配置即所得的程度不用自己寫編碼循環(huán)、不用管理復用/釋放緩沖只要描述我想對畫面做什么剩下交給框架。讀完本文你將掌握Transformer 離線轉(zhuǎn)碼與 Effect 渲染管線的前世今生依賴引入與官方 demo 的運行路徑裁剪、旋轉(zhuǎn)、縮放等幾何變換的落地寫法亮度、對比度、HSL、色彩 LUT 等調(diào)色效果的組合姿勢多段視頻拼接與導出進度監(jiān)聽的方法避免轉(zhuǎn)碼翻車的性能與調(diào)試清單先搞清楚一個前提為什么要用 Transformer 而不是實時濾鏡實時濾鏡demos/gl里的GlEffect鏈路處理的是播放中的每一幀畫面直接送屏幕不落盤。而本文的主角 Transformer 是離線導出它讀取輸入源逐幀送入VideoFrameProcessor組成的處理鏈再交給DefaultEncoderFactory編碼、DefaultMuxer封裝最終寫成一個新文件。一句話區(qū)分實時濾鏡是看得見摸不著Transformer 視頻轉(zhuǎn)碼是看得見、改得動、存得下。渲染架構(gòu)見官方架構(gòu)圖它解釋了視頻幀在處理器之間流轉(zhuǎn)的方式這張圖來自 docs/glossary.md值得反復看。理解它的關(guān)鍵是記住三個名詞組件職責Effect描述對幀做什么的抽象接口視頻效果與音頻處理器兩大類VideoFrameProcessor幀處理器的執(zhí)行引擎管理 OpenGL 紋理與線程Transformer導出編排器連接讀取、處理、編碼、封裝四個環(huán)節(jié)環(huán)境準備依賴、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 中的最新發(fā)布信息為準。如果你只是想先跑起來無需從零搭工程。項目自帶一個完整的轉(zhuǎn)碼 demo代碼在 demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/它會展示輸入畫面、實時顯示導出進度、并在完成后回放輸出文件。建議對照它閱讀本文的每個示例——里面用到的PeriodicVignetteShaderProgram周期性暗角著色器正是自定義效果的現(xiàn)成范本。任務一讓畫面轉(zhuǎn)起來——幾何變換的最短路徑先從一個最樸素的需求切入用戶錄了一段豎屏視頻想順時針轉(zhuǎn) 90° 再橫著看。在 Transformer 的世界里這不需要碰任何矩陣數(shù)學——直接使用現(xiàn)成的ScaleAndRotateTransformationScaleAndRotateTransformation rotation new ScaleAndRotateTransformation.Builder() .setRotationDegrees(90f) // 逆時針 90 度配合視頻自帶旋轉(zhuǎn)可得到豎轉(zhuǎn)橫 .build();真正決定轉(zhuǎn)完怎么擺放的是Presentation效果。它控制輸出畫幅與輸入畫面之間的適配策略對應測試資源里那些scale_to_fit、stretch_to_fit、crop的命名Presentation presentation new Presentation.Builder() .setWidth(1080) .setHeight(1920) .build(); // 默認走 scaleToFit可改為 setScaleToFitBehavior 精細控制下面兩張測試幀是同一段素材在旋轉(zhuǎn)后的效果對比第一張是原始幀第二張是旋轉(zhuǎn)后的輸出任務二給畫面換氣質(zhì)——把調(diào)色玩出排列組合幾何變換之外library/effect還內(nèi)置了一整套顏色處理效果它們?nèi)繉崿F(xiàn)RgbMatrix或RgbFilter接口可以任意串聯(lián)。下面是隨手可用的幾個效果類參數(shù)含義典型用途Brightness-1 ~ 10 為不變整體提亮/壓暗Contrast0 ~ 21 為不變增強/減弱明暗反差HslAdjustment色調(diào)/飽和度/亮度三維氛圍調(diào)色RgbAdjustment單通道偏移冷調(diào)/暖調(diào)偏色SingleColorLut顏色查找表復刻復古、賽博等風格以最常見的先提亮再降飽和為例兩個效果按順序塞進一個Effects容器即可Effects effects new Effects( /* audioProcessors */ ImmutableList.of(), /* videoEffects */ ImmutableList.of( new Brightness(0.1f), // 亮度加 0.1 new HslAdjustment.Builder() .adjustSaturation(-0.3f) // 飽和度下調(diào) 30% .build())); EditedMediaItem item new EditedMediaItem.Builder(mediaItem) .setEffects(effects) .build();效果列表的執(zhí)行順序就是渲染管線的串聯(lián)順序誰在前誰先生效。對比一下測試素材里灰度化前后的效果能直觀看到單幀處理的威力任務三進階玩法——畫中畫、貼紙與文字疊加如果你覺得調(diào)色不過癮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 的組裝方式。疊加了默認文字水印的幀長這樣任務四拼盤輸出——多段視頻合成一個文件現(xiàn)在把前面所有能力串起來完成多段素材 各自特效 導出成一個 MP4的完整閉環(huán)。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();隨后創(chuàng)建Transformer實例注冊監(jiān)聽器并啟動導出。導出是異步的進度通過ProgressHolder輪詢獲取Transformer transformer new Transformer.Builder(context) .addListener(new Transformer.Listener() { Override public void onCompleted(Composition composition, ExportResult exportResult) { // 導出成功result 中包含時長、編解碼耗時等統(tǒng)計 } Override public void onError( Composition composition, ExportResult exportResult, ExportException error) { // 導出失敗根據(jù) 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。性能優(yōu)化與常見翻車點離線轉(zhuǎn)碼是重活幾個高頻問題提前給你排雷分辨率匹配輸出分辨率應盡量貼近源分辨率避免無謂的縮放上采樣Presentation的scaleToFit策略默認會等比適配別隨手設一個與源相差過大的尺寸。音頻處理器別亂掛Effects的audioProcessors列表只接收AudioProcessor如SonicAudioProcessor變速、SilenceSkippingAudioProcessor去靜音誤把視頻效果塞進去會在構(gòu)建階段直接拋異常。HDR 輸入要交代部分效果如Brightness明確不支持 HDR遇到 HDR 素材會校驗失敗。傳參前先確認源格式必要時走 tone mapping 轉(zhuǎn) SDR。線程模型Transformer實例必須由單一應用線程訪問絕大多數(shù)場景就是主線程跨線程操作會觸發(fā)非法狀態(tài)異常。看日志導出階段的關(guān)鍵節(jié)點會輸出ExoPlayerImplInternal/DefaultVideoFrameProcessor等模塊日志配合 docs/debug-logging.md 里LogcatLogger的接法能快速定位是哪一環(huán)卡住。真機驗證編碼能力不同設備支持的編碼器參數(shù)不同TransformationRequest中聲明的目標參數(shù)可能被降級onFallbackApplied回調(diào)會告訴你實際用了什么??偨Y(jié)與下一步回顧這條從播放到轉(zhuǎn)碼的能力升級路徑你已經(jīng)拿到了三個關(guān)鍵認知Transformer 視頻轉(zhuǎn)碼的核心是描述意圖而非手寫管線Effect接口是幾何、調(diào)色、疊加三大類效果的統(tǒng)一入口Composition把單素材編輯升級為多段拼接與混流。測試素材下積累了數(shù)百張首幀截圖見testdata/src/test/assets/media/bitmap/sample_mp4_first_frame/任何自定義效果都能用它快速肉眼驗證。如果想更進一步建議按這個順序深入自定義GlEffect/GlShaderProgram參考 demos/transformer/src/main/assets/ 下的 GLSL 模板與PeriodicVignetteShaderProgram的實現(xiàn)寫出你自己的風格化效果吃透TransformationRequest掌握視頻/音頻 MIME、碼率、幀率的精細控制研究 demo 的矩陣工廠MatrixTransformationFactory.java 展示了如何用MatrixTransformation實現(xiàn)更自由的視角變換。如果這篇 ExoPlayer 視頻轉(zhuǎn)碼實戰(zhàn)對你有幫助點贊收藏支持一下。下一期我們聊聊如何把 Transformer 的導出管線與demos/gl的實時濾鏡鏈路打通讓預覽即導出、所見即所得敬請期待。【免費下載鏈接】ExoPlayerAn extensible media player for Android項目地址: https://gitcode.com/gh_mirrors/exop/ExoPlayer創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考