(十八)深入了解 AVFoundation-編輯:添加背景音樂與音量控制(下)——實戰篇

一、功能目標回顧

在理論篇中,我們系統地介紹了如何使用 AVFoundation 添加背景音樂音軌,并通過?AVMutableAudioMix?與?AVMutableAudioMixInputParameters?實現多音軌混音與音量控制。我們了解了諸如淡入淡出、靜音控制、動態音量曲線等核心技術細節。

本篇將以實際代碼為基礎,結合我們之前構建的 AVFoundation 編輯 Demo 工程,落地實現以下功能:

1. 為視頻添加背景音樂

  • 支持用戶在時間線上額外指定一段音頻資源;
  • 背景音樂可以與原聲音軌同時存在,并被正確插入合成軌中。

2. 多音軌合成(原聲 + 背景樂)

  • 原聲與背景音樂將分別被插入不同的音頻軌道;
  • 最終合成時,兩條音軌將同時輸出,并支持混音控制。

3. 控制音軌音量

  • 可分別為原聲與背景音樂設置不同的音量級別;
  • 背景音樂默認比原聲略低,以避免搶占對白。

4. 實現背景音樂淡入淡出

  • 支持設置淡入時長(如:前2秒從0過渡到1);
  • 支持設置淡出時長(如:最后3秒從1降到0);
  • 音量變化基于時間段動態計算,提升用戶聽覺體驗。

5. 支持播放與導出場景下的音頻混音

  • 混音效果不僅適用于?AVPlayerItem?播放;
  • 也可用于?AVAssetExportSession?導出,確保輸出視頻具備完整聲音效果。

這些功能將逐步融入我們現有的合成架構中,既保持結構清晰,也為后續功能擴展(如多段配樂、音效插入、音量自動化)打下良好基礎。

二、Demo 架構回顧與準備工作

在我們此前構建的 AVFoundation 編輯 Demo 中,整體設計圍繞「可組合、可導出、可復用」展開,核心接口抽象清晰,便于后續拓展新的能力。為了實現背景音樂與音量控制,我們將基于現有結構進行適度擴展。

2.1 原有架構回顧

此前的編輯系統大致由以下幾個核心組件構成:

  • PHComposition 協議:定義合成結構應提供的能力:生成?AVPlayerItem?與?AVAssetExportSession。
  • PHBasicComposition:基于?AVMutableComposition?構建的默認合成模型,用于拼接視頻與原聲音軌。
  • PHTimeLine:?用于描述時間軸上出現的媒體資源,包括?videoItems(視頻片段)和?audioItems。
  • PHBaseCompositionBuilder:負責將?PHTimeLine?構建為一個?PHComposition?實例。

該結構已經支持了基礎的剪輯與拼接能力,但尚未具備音頻混音與動態控制功能。

2.2 新增音頻混音能力:架構擴展方案

為了支持背景音樂與音量控制,我們將進行以下結構升級:

? 新增:PHAudioMixComposition

  • 遵循?PHComposition?協議
  • 代替原有的PHBasicComposition
  • 在原有?AVMutableComposition?基礎上,添加對?AVMutableAudioMix?的支持
  • 對外提供?playerItem?和?exportSession?接口,并自動附加混音配置

? 新增:PHAudioMixCompositionBuilder

  • 遵循?PHCompositionBuilder?協議
  • 代替原有的?PHBaseCompositionBuilder
  • 負責將?PHTimeLine?中的視頻、音頻資源統一合成,同時構建對應的音量控制參數(淡入淡出等)
  • 返回?PHAudioMixComposition?實例

? 擴展:PHTimeLine?添加背景音樂支持

class PHTimeLine: NSObject {/// 視頻資源數組var videoItmes = [PHVideoItem]()/// 音頻資源數組var audioItems = [PHAudioItem]()/// 背景音樂var musicItems = [PHMusicItem]()}

2.3 構建與導出流程調整

通過上述結構升級,我們的播放與導出流程也將相應調整:

原流程:

PHBaseCompositionBuilder → PHBasicComposition → AVPlayerItem / AVAssetExportSession

新流程(支持音量控制):

PHAudioMixCompositionBuilder → PHAudioMixComposition(包含 AVAudioMix) → AVPlayerItem / AVAssetExportSession

最終,在用戶層只需更換構建器類,即可無感接入新的混音邏輯。

三、添加背景音樂與構建混音輸出

在本節中,我們正式將理論篇中的混音控制能力落地到 Demo 架構中,借助兩個核心類的設計,全面實現了“添加背景音樂 + 音量控制 + 支持播放與導出”的閉環。

3.1?PHAudioMixComposition:音頻混合合成對象

PHAudioMixComposition?作為最終的合成輸出載體,遵循?PHComposition?協議,提供兩大能力:

  • 構建可播放的?AVPlayerItem;
  • 構建可導出的?AVAssetExportSession。

其核心結構如下:

class PHAudioMixComposition: PHComposition {private var audioMix: AVAudioMixprivate var composition: AVCompositioninit(audioMix: AVAudioMix, composition: AVComposition) {self.audioMix = audioMixself.composition = composition}func makePlayableItem() -> AVPlayerItem? {guard let asset = composition.copy() as? AVAsset else { return nil }let playerItem = AVPlayerItem(asset: asset)playerItem.audioMix = audioMixreturn playerItem}func makeExportSession(presetName: String) -> AVAssetExportSession? {guard let asset = composition.copy() as? AVAsset else { return nil }let session = AVAssetExportSession(asset: asset, presetName: presetName)session?.audioMix = audioMixreturn session}
}

通過統一附加?audioMix,我們實現了音量變化效果在播放與導出兩個流程中保持一致

3.2?PHAudioMixCompositionBuilder:混音構建器

該類實現了?PHCompositionBuilder?協議,是實際執行素材拼接與混音參數構建的主要模塊:

class PHAudioMixCompositionBuilder: PHComositionBuilder {private let composition = AVMutableComposition()private let timeLine: PHTimeLineinit(timeLine: PHTimeLine) {self.timeLine = timeLine}func buildComposition() -> (any PHComposition)? {_ = self.addTrack(with: .video, mediaItems: timeLine.videoItmes)_ = self.addTrack(with: .audio, mediaItems: timeLine.audioItems)let musicTrack = self.addTrack(with: .audio, mediaItems: timeLine.musicItems)guard let musicTrack = musicTrack else { return nil }guard let audioMix = self.buildAudioMix(track: musicTrack) else { return nil }return PHAudioMixComposition(audioMix: audioMix, composition: composition)}
}

在合成構建流程中,PHAudioMixCompositionBuilder?完成了以下幾個關鍵任務:

  • 統一插入所有視頻、音頻軌道;
  • 單獨處理背景音樂軌;
  • 構建 AVAudioMixInputParameters 來實現音量變化控制;
  • 最終生成 PHAudioMixComposition 返回給外部使用。

3.3 構建混音參數的關鍵邏輯

在?buildAudioMix?中,我們讀取了?PHTimeLine.musicItems?中的首個?PHAudioItem,并遍歷其音量控制曲線?volumeAutomation:

private func buildAudioMix(track: AVMutableCompositionTrack) -> AVAudioMix? {guard let musicItem = self.timeLine.musicItems.first else { return nil }let parameters = AVMutableAudioMixInputParameters(track: track)for automation in musicItem.volumeAutomation {parameters.setVolumeRamp(fromStartVolume: automation.startVolume, toEndVolume: automation.endVolume, timeRange: automation.timeRange)}let audioMix = AVMutableAudioMix()audioMix.inputParameters = [parameters]return audioMix
}

這段邏輯確保我們可以靈活地:

  • 控制音量隨時間變化(淡入、淡出、靜音段落等);
  • 支持將多個?volumeAutomation?分段組合成完整的控制曲線;
  • 保持配置結構可擴展、可預覽、可導出。

3.4 媒體軌道添加邏輯:支持異步加載資源

addTrack(with:mediaItems:)?方法支持批量插入素材軌,同時采用異步?loadTracks?方式加載素材:

for mediaItem in mediaItems {mediaItem.asset?.loadTracks(withMediaType: mediaType, completionHandler: { [weak self] tracks, error in// 插入邏輯...})
}

四、結語

至此,我們已經完成了為視頻添加背景音樂與控制音量的全部實戰流程。

相比理論篇中的 API 介紹與功能分析,本篇將這些能力真正融入到了項目架構中。我們通過構建新的?PHAudioMixComposition?與?PHAudioMixCompositionBuilder,讓混音效果不僅可控,而且具備良好的復用性和擴展性。

背景音樂的添加不再是“硬塞進一條音軌”,而是具備了細膩的時間控制和動態音量設計:我們可以淡入淡出、隨時間變化音量,甚至為不同片段設置不同的聽覺節奏。

這不僅豐富了視頻剪輯系統的表現力,也為后續更多音頻功能(如自動靜音、節奏分析、UI 實時控制音量等)打下了堅實基礎。

在下一篇中,我們將繼續擴展剪輯系統的能力,敬請期待。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/913487.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/913487.shtml
英文地址,請注明出處:http://en.pswp.cn/news/913487.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何在新機器上設置github完成內容git push

如果你在一臺新的機器上git pull 倉庫,完成修改,然后git push,會發現下面錯誤: Username for https://github.com: xiaomaolv Password for https://xiaomaolvgithub.com: remote: Support for password authentication was rem…

Rust 注釋

Rust 注釋 引言 Rust 編程語言以其內存安全、并發支持和高性能等特點在軟件開發領域獲得了廣泛的關注。在Rust編程中,注釋是一種非常重要的元素,它不僅可以幫助程序員理解代碼,還可以提高代碼的可維護性和可讀性。本文將詳細介紹Rust中的注釋…

Flink Oracle CDC 環境配置與驗證

一、Oracle 數據庫核心配置詳解 1. 啟用歸檔日志(Archiving Log) Oracle CDC 依賴歸檔日志獲取增量變更數據,需按以下步驟啟用: 非CDB數據庫配置: -- 以DBA身份連接數據庫 CONNECT sys/password AS SYSDBA; -- …

ssh: Could not resolve hostname d: Temporary failure in name resolution

關于不能本機上傳文件夾到服務器上的一個問題的記錄。 scp -r "D:\***\datasets" usernamexxxxxx:接收文件夾名 一直報錯:ssh: Could not resolve hostname d: Temporary failure in name resolution 反復嘗試發現無果之后想起來,在傳輸的時候…

2025年的前后端一體化CMS框架優選方案

以下是結合技術生態、開發效率和商業落地驗證,整理的2025年前后端一體化CMS框架優選方案:一、?主流成熟框架組合?1. ?React Node.js (Express/Next.js)??前端?:React生態成熟,配合Redux狀態管理,適合復雜后臺界…

《聲音的變形記:Web Audio API的實時特效法則》

用戶期待更豐富、更具沉浸感的聽覺體驗時,基于Web Audio API實現的實時音頻特效,就像是為這片森林注入了靈動的精靈,讓簡單的聲音蛻變為震撼人心的聽覺盛宴。回聲特效帶來空間的深邃回響,變聲效果賦予聲音全新的個性面貌。接下來&…

LLM場景下的強化學習【PPO】

適合本身對強化學習有基本了解 一、什么是強化學習 一句話:在當前狀態(State)下,智能體(Agent)與環境(Environment)交互,并采取動作(Action)進入下一狀態,過程中獲得獎勵(Reward,有正向有負向),從而實現從…

Python爬蟲實戰:研究chardet庫相關技術

1. 引言 1.1 研究背景與意義 在互聯網信息爆炸的時代,網絡數據采集技術已成為信息獲取、數據分析和知識發現的重要手段。Python 作為一種高效的編程語言,憑借其豐富的第三方庫和簡潔的語法,成為爬蟲開發的首選語言之一。然而,在網絡數據采集中,文本編碼的多樣性和不確定…

回溯題解——全排列【LeetCode】

46. 全排列 一、算法邏輯(逐步通順講解每一步思路) 該算法使用了典型的 回溯(backtracking) 狀態數組 思路,逐層遞歸生成排列。 題目目標:給定一個無重復整數數組 nums,返回其所有可能的全排…

RICE模型或KANO模型在具體UI評審時的運用經驗

模型是抽象的產物,結合場景才好說明(數據為非精確實際數據,僅供參考,勿照搬)。 ??案例一:RICE模型解決「支付流程優化」vs「首頁動效升級」優先級爭議?? ??背景??:APP電商模塊在迭代中面臨兩個需求沖突——支付團隊主張優化支付失敗提示(減少用戶流失),設計…

緩存中間件

緩存與分布式鎖 即時性、數據一致要求不高的 訪問量大且更新頻率不高的數據 (讀多,寫少) 常用緩存中間件 redis Spring 如果用spring的情況下,由于redis沒有受spring的管理, 則我們需要自己先寫一個redis的配置類&…

大語言模型全方位解析:從基礎認知到RESTful API應用

文章目錄 前言一、初見大模型1.1 大語言模型基本知識了解(一)日常可能用到的大語言模型(二)大模型的作用(三)核心價值 1.2 大模型與人工智能關系1.3 大語言模型的“前世今生”與發展1.3.1 大語言模型的發展…

網安系列【11】之目錄穿越與文件包含漏洞詳解

文章目錄 前言一 目錄穿越漏洞1.1 什么是目錄穿越?1.2 目錄穿越的原理1.3 目錄穿越的常見形式1.3.1 基本形式1.3.2 編碼繞過1.3.3 絕對路徑攻擊 1.4 實戰案例解析1.4.1 案例1:簡單的目錄穿越1.4.2 案例2:編碼繞過 1.5 目錄穿越的危害 二、文件…

uri-url-HttpServletRequest

1. 使用HttpServletRequest UrlPathHelper 解析 出 url路徑 org.springframework.web.util.UrlPathHelper 是 Spring 框架中用于處理 HTTP 請求路徑的一個工具類,它幫助解析和處理與請求路徑相關的細節。特別是 getLookupPathForRequest(HttpServletRequest request…

Ubuntu22.04安裝p4顯卡 nvidia-utils-570-server 570.133.20驅動CUDA Version: 12.8

Ubuntu22.04安裝p4顯卡 nvidia-utils-570-server 570.133.20驅動CUDA Version: 12.8專業顯卡就是專業顯卡,盡管p4已經掉到了白菜價,官方的支持卻一直都保持,比如它可以裝上cuda12.8,這真的出乎我意料。NVIDIA Tesla P4顯卡的主要情況Pascal架…

工業日志AI大模型智能分析系統-前端實現

目錄 主要架構 前端項目結構 1. 核心實現代碼 1.1 API服務封裝 (src/api/log.ts) 1.2 TS類型定義 (src/types/api.ts) 1.3 Pinia狀態管理 (src/stores/logStore.ts) 1.4 日志分析頁面 (src/views/LogAnalysis.vue) 1.5 日志詳情組件 (src/components/LogDetail.vue) 2…

C++內存泄漏排查

引言 C內存泄漏問題的普遍性與危害內存泄漏排查大賽的背景與目標文章結構和主要內容概述 內存泄漏的基本概念 內存泄漏的定義與類型(顯式、隱式、循環引用等)C中常見的內存泄漏場景(指針管理不當、資源未釋放等)內存泄漏對程序性能…

20250706-4-Docker 快速入門(上)-常用容器管理命令_筆記

一、常用管理命令1. 選項1)ls功能:列出容器常用參數:-a:查看所有容器包含退出的-q:列出所有容器ID-l:列出最新創建的容器狀態使用技巧:容器很多時使用dock…

基于 Camunda BPM 的工作流引擎示例項目

項目介紹 這是一個基于 Camunda BPM 的工作流引擎示例項目,包含完整的后臺接口和前端頁面,實現了流程的設計、部署、執行等核心功能。 技術棧 后端 Spring Boot 2.7.9Camunda BPM 7.18.0MySQL 8.0JDK 1.8 前端 Vue 3Element PlusBpmn.jsVite 功能…

Day06_刷題niuke20250707

試卷01: 單選題 C 1. 在C中,一個程序無論由多少個源程序文件組成,其中有且僅有一個主函數main().說法是否正確? A 正確 B 錯誤 正確答案:A 官方解析: 在C程序設計中,一個完整的程序確實有且僅有一個main函數作為程序的入口點,這…