分享影片的最佳做法

許多人會使用 Android 裝置分享影片,由於共享應用程式會執行處理作業,因此接收影片的品質通常會低於原始影片的品質。本文件說明如何最佳化共享影片的品質,並避免一些常見的影片處理陷阱。如要最佳化分享 HDR 影片內容,請參閱本頁面的使用 Transformer 模組將 HDR 轉碼為 SDR

重點是在準備分享影片時,維持穩定的解析度並盡可能維持視訊品質。

共用管道

圖 1 說明分享影片的典型流程:

分享影片管道 圖 1. 影片分享管道。

管道包含下列步驟:

  1. 拍攝並編碼影片,可能會在拍攝期間加入特效。 或者,使用者也可以略過這個步驟,並從其他應用程式預錄的儲存影片中選取影片。
  2. 編輯、過濾、修飾或處理影片。
  3. 縮放影片或調整影片大小,以便進行轉碼。
  4. 將影片轉碼以便分享。步驟 2 中的篩選通常會做為此步驟的一部分套用。

管道中有兩個步驟,可讓您設定決定影片品質的參數:在初始錄製期間進行編碼,以及在分享前進行轉碼。此外,您可能要在最終轉碼步驟之前重新調整影片比例,這也會影響品質。

建議

表 1 列出影片品質的五個主要參數,並指出有哪些步驟可以使用。

參數 擷取 分享
個人資料
解析度
位元率
量化參數 (QP) (很少)
B 影格

表 1. 決定影片畫質的主要參數

設定檔

為了獲得更好的結果,請使用特定轉碼器提供的更進階設定檔。如果是 AVC 編碼,請選取「高設定檔」和「等級 4」。

解析度、裁剪和縮放

您可以在轉碼以便分享之前,在縮放步驟中變更拍攝影片的初始解析度,但縮放功能可能會降低影片畫質。建議您避免資源調度,並選取可用於整個管道的初始編碼解析度。另請注意,過度裁剪會導致圖片畫質不佳,尤其是在調高裁剪圖片時。請遵守下列規範:

  • 選擇的解析度至少要和最終分享解析度一樣大。
  • 除非所有中間步驟都是專為支援較高的解析度 (例如初始拍攝期間的位元率較高) 而設計,否則擷取解析度不應大幅超過共用解析度。

    • 如果共用編碼產生的解析度為 720x1280,建議您採用 720x1280 的擷取解析度。
    • 如果拍攝與分享的中間步驟包含裁剪,請使用較高的擷取解析度 (例如 1080x1920),然後提高拍攝位元率來處理額外的像素。
  • 極端裁剪會導致圖片畫質不佳,尤其是在裁剪後的圖片放大時更是如此。

  • 避免從較低解析度提高到較高的解析度。向上擴充程式會嘗試建立不存在的詳細資料。從一開始就保留想要的 解析度較高的解析度。

  • 如果此值必須較大,請調整編碼參數。舉例來說,如果放大後的解析度為像素的兩倍,請將位元率的兩倍。

解析度和位元率彼此相關。舉例來說,透過分享管道傳輸高解析度影片,最終轉碼成較低的位元率會產生畫質較低的圖片。隨著位元率降低,有些交叉點的解析度會開始變小,以便獲得更好的結果:

位元率 解析度
5 Mbps 以上 1080x1920
1.5 至 5 Mbps 以上 720x1280
1.5 Mbps 以下 對等 SD 版本。長寬比 9:16 的像素計數約為 416x736

表 2. 位元率與解析度

許多熱門應用程式都會以 720p 以下的解析度分享影片。資料顯示 720p 解析度是 1.5 至 5 Mbps 之間的適當位元率目標。

位元率

錄製中

使用較高的編碼位元率可提升影片品質。建議您選擇符合原生相機應用程式的位元率。如果是 720x1280 解析度,建議擷取位元率為 10 Mbps。

由於擷取編碼會在裝置端進行,因此您可以使用較高的位元率來彌補大部分的共用步驟轉換作業,幾乎沒有負面影響。產生的檔案較大時,只會用於在裝置上操控。

您可以在最終轉碼步驟降低位元率,如表 2 所示。

分享

位元率與上傳的影片大小直接相關,因此在分享時間最有幫助。需要在影片品質、檔案傳輸時間和雲端儲存空間的費用之間取捨

在這個階段,選擇編碼設定檔、B 影格和 QP 邊界值,在擷取期間也更為重要。

建議您使用 4 至 5 Mbps 的位元率 (適用於 720x1280 解析度),以確保良好的視覺品質。

量化參數 (QP)

在 Android 12 以上版本中,QP 金鑰會標準化,並可在 MediaFormat API 和 NDK 媒體程式庫中找到。在舊版 Android 中,只有使用 MediaFormat 設定中使用供應商專屬金鑰的架構函式,才能使用 QP 操縱功能。

錄製中

影片擷取期間,請使用位元率控制設定,而非 QP 設定 (有時可能無法使用這些設定)。

我們不建議您針對 720x1280 的擷取位元率調整 QP 設定。如果擷取位元率大幅降低,在 720x1280 時,QP 設定應低於 5 Mbps,因此可在提升品質之間取捨,將 QP 設定設為 40,不讓轉碼器太常頻繁地超出目標位元率。

分享

建議您將 QP 上限值設為 40,尤其是在位元率低於 4 Mbps 時。儘管這樣可以確保編碼影片的品質最低,但可以產生位元率較高的結果。位元率的增加取決於影片的複雜程度雖然共用應用程式可能會容忍影片產生的位元率有些許差異,但可能無法容忍增加超過特定門檻。

如要限制位元率提高,您可以在限制較少 (較高) 的 QP 邊界重新編碼影片以便分享。這樣編碼人員就能更自由地提升品質 並保留影片的其他部分由於該影片屬於轉碼作業,因此您可以重新編碼要分享的影片。您已經拍攝了想要分享的影片。

缺點是使用這些參數重複轉碼步驟會增加分享影片所需的時間。要縮短這段延遲時間,其中一種方法是檢查部分轉碼的影片,判斷是否不在位元率的容忍度範圍內。否則,您可以停止轉碼,然後使用更適當的 QP 參數再試一次。

B 影格和編碼設定檔

建議只在分享步驟期間使用 B 影格,且只有在執行 Android 10 或以上版本時才能使用。

因為並非所有裝置都支援主要或高設定檔,應用程式應使用 CodecCapabilities 檢查支援的編碼設定檔。請使用 AVC 編碼器支援的最高設定檔:高 > 主要 > 基準。為確保最佳結果,使用基準設定檔時,請不要設定 B 影格 (KEY_LATENCYKEY_MAX_B_FRAMES),因為部分編碼器可能會設定失敗。

以下程式碼片段假設的 'MediaFormat format' 將用來設定 AVC 編碼器

Android 10

API 29 以上版本

使用支援的最高設定檔,並將 B-Frame 參數設為 1:

format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_MAX_B_FRAMES, 1);

在這種情況下,請不要設定 KEY_LATENCY

Android 8、8.1 和 9

API 26、27、28

使用支援的最高設定檔,但停用 B 影格產生功能。這符合這些系統版本中 MediaMuxer 的部分限制

format.setInt32(KEY_PROFILE, AVCProfileHigh);
format.setInt32(KEY_LATENCY, 1);

KEY_LATENCY 值禁止轉碼器產生 B 影格,但仍可運用其他轉碼器的效率。

如果應用程式未使用 MediaMuxer 組合最終輸出檔案,您可以將 KEY_LATENCY 值 (而非 1) 設為 2,藉此啟用 B 影格。這應該可讓轉碼器產生 B 影格。

Android 7.1 以下版本

API 25 以下版本

使用基準設定檔可確保結果最安全。

format.setInt32(KEY_PROFILE, AVCProfileBaseline);

在 7 版之前,Android 開放原始碼計畫僅支援基準設定檔。不過,原始設備製造商 (OEM) 可能是因為使用供應商專屬設定檔,在部分裝置上啟用了主要/高階設定檔。

如果應用程式未使用 MediaMuxer,只要轉碼器支援,您就可以使用主要或高階設定檔。目前沒有可控制 B 影格數的公開格式金鑰。

使用 Transformer 模組將 HDR 轉碼為 SDR

從 Android 13 (API 級別 33) 開始,建議您使用 Jetpack Media3 的 Transformer 模組,將 HDR 內容分享到不支援 HDR 的應用程式、服務和裝置。Transformer 模組的運作方式是將輸入的 HDR 影片串流轉換成 SDR,並將結果儲存為 MP4,這樣就能成功播放,而不會失去細節或影像亮度。

注意:在搭載 Android 12 (API 級別 32) 至 Android 7.0 (API 級別 24) 之間的裝置上,Transformer 模組的運作方式有所不同。如果裝置支援 HDR,應用程式就會播放內容,而不進行色調對應。如果裝置不支援 HDR,就會擲回錯誤,指出不支援 HDR 色調對應。

以下程式碼會設定 Transformer,將輸入內容對應至 SDR,並以輸入格式 (例如 H.264/AVC) 重新編碼:

Kotlin

val transformer = Transformer.Builder(context)
    .setTransformationRequest(
        TransformationRequest.Builder()
            .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR)
            .build())
    .addListener(/* ... */)
    .build()

Java

Transformer transformer = new Transformer.Builder(context)
    .setTransformationRequest(
        new TransformationRequest.Builder()
            .setHdrMode(TransformationRequest.HDR_MODE_TONE_MAP_HDR_TO_SDR)
            .build())
    .addListener(/* ... */)
    .build();

如要試用色調對應功能,請參閱 Transformer 試用版應用程式

您也可以使用 MediaCodec 設定色調對應,但實作方式較為複雜。詳情請參閱 MediaCodec 參考說明文件。