15.Chromium指紋瀏覽器開發教程之WebAudio指紋定制

WebAudio指紋概述

瀏覽器中的 WebAudio API 提供了豐富的功能,其中包括了大量生成和處理音頻數據的API。WebAudio API 的音頻指紋技術是一種利用音頻信號的特征來唯一標識音頻的技術。因為WebAudio API 提供了豐富的音頻處理功能,包括合成、過濾、分析等,通過一系列功能組合,可以使生成的音頻指紋具有一定的獨特性。生成音頻指紋的過程通常涉及到對音頻數據進行數學運算或特征提取,這使得生成的指紋在一定程度上是穩定的,即使音頻本身有一定的變化也不會影響其唯一性。而且Web Audio API 提供了實時處理音頻數據的能力,因此可以用于實時生成和識別音頻指紋。

WebAudio API主要用在AudioContext上下文中,在進行任何其他操作之前,始終需要創建一個AudioContext的實例,如圖4-7所示。

在有了音頻來源之后,通過節點壓縮,就可以得到Buffer輸出了。在實際的WebAudio API 操作過程中,通用的做法是創建單個AudioContext實例,并在所有后續處理中重復使用。每個AudioContext實例都具有一個目標屬性,該屬性用于表示該上下文中所有音頻的目標。此外,還存在一種特殊類型的AudioContext,即OfflineAudioContext。在獲取音頻指紋的時候,通常是會創建OfflineAudioContext,主要原因在于它不會將音頻呈現給設備硬件,而是快速生成音頻并將其保存到AudioBuffer中。因此,OfflineAudioContext的目標是內存中的數據結構,而常規的AudioContext的目標是音頻設備。

創建OfflineAudioContext實例時,需要傳遞三個參數:

  1. 通道數:通道數表示音頻數據中的聲道數量。在數字音頻中,通常有單聲道和立體聲兩種通道配置。單聲道通常用于單一音頻源,而立體聲則包含左右兩個獨立的聲道,用于模擬左右聲源的位置和方向。通道數還可以擴展到更多聲道,如環繞聲,以提供更加沉浸式的音頻體驗。
  2. 樣本總數:樣本總數指的是音頻數據中包含的采樣數量。音頻數據是通過對連續時間信號進行采樣來獲取的,每個采樣點對應著一個特定時間點上的音頻振幅值。樣本總數決定了音頻的持續時間,即音頻的長度。采樣率和樣本總數共同決定了音頻的時長,樣本總數越多,音頻的時長就越長。
  3. 采樣率:采樣率表示每秒鐘對聲音信號進行采樣的次數,單位為赫茲Hz,采樣率決定了數字音頻的精度和質量,以及其能夠表示的頻率范圍。常見的標準采樣率包括44.1 kHz和48 kHz,它們通常用于CD音質和音頻制作。更高的采樣率,如96 kHz或192kHz可以提供更高的音頻質量和更廣的頻率響應范圍,但也會增加文件大小。

Oscillator振蕩器是一種產生周期性波形的電子設備或軟件組件。在音頻領域中,振蕩器通常用于生成聲音信號的基礎波形,例如正弦波、方波、鋸齒波等。這些基礎波形可以用于合成各種聲音,是合成器和音頻處理中的重要組件之一。振蕩器通過產生連續的電壓或數字信號來生成波形。在軟件中,振蕩器通常是由算法來模擬的,這些算法根據所需的波形形狀和參數生成連續的樣本值。在處理音頻時需要一個來源,振蕩器是一個很好的選擇,因為它是通過數學方法生成樣本的,可以生成具有指定頻率的周期波形。

壓縮節點是一種用于動態范圍壓縮的節點類型。它可以降低音頻信號的動態范圍,即減小最響亮部分與最安靜部分之間的差異,從而提高音頻的平均音量并減少峰值。壓縮節點通常用于音頻信號處理的動態范圍控制,以確保音頻在播放過程中的一致性和平衡。壓縮節點通常作為音頻處理圖中的一個節點,與其他節點,如聲音源、效果器等連接在一起,以對輸入信號進行壓縮處理。通過調整壓縮節點的參數,可以控制壓縮的程度和效果,從而實現對音頻信號動態范圍的調節和控制。

AudioBuffer是WebAudio API中表示音頻數據的數據結構。它用于存儲音頻樣本的實際數據,并提供了一組函數來訪問和操作這些數據。在WebAudio API中,AudioBuffer通常作為音頻源節點的輸入,用于播放音頻或將其傳遞給其他音頻處理節點進行進一步處理。AudioBuffer中包含音頻數據的實際樣本,這些樣本表示音頻波形在離散時間點上的振幅值。音頻數據可以來自于多種來源,例如從服務器加載、用戶錄制或通過WebAudio API生成。每個AudioBuffer實例都具有固定的采樣率和通道數。這些屬性在創建AudioBuffer時被指定,并決定了AudioBuffer中存儲的音頻數據的格式和結構。此外,AudioBuffer提供了一組函數來訪問和操作存儲的音頻數據。例如,可以使用getChannelData獲取特定通道的音頻數據,并使用set修改音頻數據的值。這些函數使得可以直接對音頻數據進行編輯和處理,例如音頻混合、剪輯、變速、變調等操作。AudioBuffer通常作為音頻源節點的輸入,用于播放音頻或將其傳遞給其他音頻處理節點進行進一步處理。通過創建AudioBufferSourceNode并將AudioBuffer作為其緩沖區傳遞給它,可以將AudioBuffer中存儲的音頻數據進行播放或傳遞給音頻圖中的其他節點。由于音頻數據以二進制格式存儲在AudioBuffer中,因此可以在Web Audio API中高效地進行音頻處理操作,而無需頻繁地將數據從JavaScript代碼中復制到Web Audio API中。

在WebAudio指紋的計算過程中,一般使用OfflineAudioContext上下文,接著設置特殊的振蕩器來作為音頻源,在經過壓縮節點操作之后,就可以使用getChannelData來獲取生成的AudioBuffer了,指紋即是通過對該Buffer的計算完成的。

let audioContext = new (window.OfflineAudioContext ||window.webkitOfflineAudioContext)(1, 44100, 44100);let outputValue;if (!audioContext) {outputValue = 0;} else {let oscillator = audioContext.createOscillator();oscillator.type = "triangle";oscillator.frequency.value = 10000;let compressor = audioContext.createDynamicsCompressor();if (compressor.threshold) compressor.threshold.value = -50;if (compressor.knee) compressor.knee.value = 40;if (compressor.ratio) compressor.ratio.value = 12;if (compressor.reduction) compressor.reduction.value = -20;if (compressor.attack) compressor.attack.value = 0;if (compressor.release) compressor.release.value = 0.25;oscillator.connect(compressor);compressor.connect(audioContext.destination);oscillator.start(0);audioContext.startRendering();audioContext.oncomplete = function(event) {outputValue = 0;let renderedBuffer = event.renderedBuffer.getChannelData(0);let bufferAsString = '';for (let i = 0; i < renderedBuffer.length; i++) {bufferAsString += renderedBuffer[i].toString();}let fullBufferHash = hash(bufferAsString);console.log('Full buffer hash: ' + fullBufferHash);for (let i = 4500; i < 5000; i++) {outputValue += Math.abs(renderedBuffer[i]);}console.log('Output value: ' + outputValue);compressor.disconnect();};}

前兩行代碼創建了一個OfflineAudioContext實例。使用離線音頻上下文允許程序處理和渲染音頻數據而不實時播放。使用window.OfflineAudioContext或window.webkitOfflineAudioContext確保代碼兼容不同的瀏覽器。使用createOscillator?創建一個振蕩器,用于生成音頻信號。使用createDynamicsCompressor?創建一個動態壓縮器節點,該節點用于減少音頻信號的動態范圍。然后將振蕩器連接到壓縮器,壓縮器再連接到音頻上下文的輸出

當渲染完成后,oncomplete 定義的函數被調用,getChannelData用于獲取渲染后的音頻數據,接著將音頻數據轉換為字符串,并計算其哈希值。代碼最后計算了特定樣本范圍內的數據的絕對值之和,這個數是音頻指紋常用的指紋數字。

WebAudio指紋獲取

本節會使用JavaScript腳本編寫一個獲取WebAudio音頻信息的腳本。這段代碼利用JavaScript的WebAudio API來生成和處理音頻數據,最終目的是生成一個音頻哈希值和一個從特定樣本范圍內計算得到的輸出值。以下是具體代碼:

從4.3.2的代碼中可以看出,音頻指紋的修改點很多,但是最終是使用getChannelData來獲取渲染后的音頻數據的,因此可以選擇該函數作為音頻指紋修改點。對其中的音頻數組進行遍歷噪聲,從而影響整個音頻。

WebAudio相關的Chromium源碼位于“src\third_party\blink\renderer\modules\webaudio”目錄之中,重點要修改的是AudioBuffer相關的,因此選擇其中的audio_buffer.cc文件作為指紋定制的文件。

getChannelData有兩個重載,具體代碼如下:

NotShared<DOMFloat32Array> AudioBuffer::getChannelData(unsigned channel_index,ExceptionState& exception_state) {if (channel_index >= channels_.size()) {exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,"channel index (" + String::Number(channel_index) +") exceeds number of channels (" +String::Number(channels_.size()) + ")");return NotShared<DOMFloat32Array>(nullptr);}return getChannelData(channel_index);}NotShared<DOMFloat32Array> AudioBuffer::getChannelData(unsigned channel_index) {if (channel_index >= channels_.size()) {return NotShared<DOMFloat32Array>(nullptr);}return NotShared<DOMFloat32Array>(channels_[channel_index].Get());}

從JavaScript代碼獲取音頻指紋的時候,只傳遞了一個參數,因此選擇第二個函數作為切入函數。該函數用于獲取音頻緩沖區中特定通道的數據。其中的函數簽名如下:

  1. NotShared<DOMFloat32Array>:返回類型是 NotShared 包裝的 DOMFloat32Array 對象。NotShared 是一種智能指針,表示該對象不應與其他對象共享。
  2. AudioBuffer:::表明該函數是 AudioBuffer 類的成員。
  3. getChannelData:接收一個無符號整數參數 channel_index,表示要獲取的數據通道索引。

然后檢查傳入的通道索引 channel_index?是否超出了音頻通道的數量。如果超出了有效范圍,表示請求的通道不存在。否則將獲取到的通道數據包裝成 DOMFloat32Array對象并返回。

由此可見,可以在最后的通道數據正式返回之前,將里邊的數據進行遍歷,挨個進行微調之后,從而完成音頻指紋定制:

??//ruyiconst base::CommandLine* ruyi_command_line =base::CommandLine::ForCurrentProcess();if (ruyi_command_line->HasSwitch(blink::switches::kRuyi)) {const std::string ruyi_fp =ruyi_command_line->GetSwitchValueASCII(blink::switches::kRuyi);absl::optional<base::Value> json_reader =base::JSONReader::Read(ruyi_fp);double webaudio_data =*(json_reader->GetDict().FindDouble("webaudio"));DOMFloat32Array* channels__ = channels_[channel_index].Get();size_t channel_size = channels__->length();for (size_t i = 0; i < channel_size; i++) {channels__->Data()[i] += (0.00001 * webaudio_data);}return NotShared<DOMFloat32Array>(channels__);}//ruyi end

修改的代碼從 JSON 中讀取一個名為 webaudio 的雙精度浮點數值,為了防止音頻數據修改過大,這里對音頻數據進行遍歷的時候,將該值按一定比例加到指定通道的音頻數據樣本上。

在修改完畢之后,可以到音頻檢測網站audiofingerprint.openwpm.com進行測試,傳遞不同參數,可以得到不同的指紋信息,如圖4-8所示:

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

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

相關文章

2025年贛教云智慧作業微課PPT模板

江西的老師們注意&#xff0c;2025年贛教云智慧作業微課PPT模版和往年不一樣&#xff0c;千萬不要搞錯了&#xff0c;圖上的才是正確的2025年的贛教云智慧作業微課PPT模版&#xff0c;贛教云智慧作業官網有問題&#xff0c;無法正確下載該模板&#xff0c;需要該模板的&#xf…

2.5.1DOS下常用工具 curl,netstat,telnet命令使用

curl命令 Win10及以上系統默認已安裝Curl&#xff0c;打開命令提示符輸入 curl --help&#xff0c;若顯示幫助信息則無需安裝 ??手動安裝方法?? 官網下載&#xff1a;訪問 curl官網 選擇Windows版本curl for Windows若需在 Windows XP 等舊系統使用&#xff0c;需選擇更…

使用Redis實現實時排行榜

為了實現一個實時排行榜系統&#xff0c;我們可以使用Redis的有序集合&#xff08;ZSet&#xff09;&#xff0c;其底層通常是使用跳躍表實現的。有序集合允許我們按照分數&#xff08;score&#xff09;對成員&#xff08;member&#xff09;進行排序&#xff0c;因此非常適合…

Linux——firewalld防火墻(筆記)

目錄 一&#xff1a;Firewalld防火墻的概述 &#xff08;1&#xff09;firewalld簡介 &#xff08;2&#xff09;firewalld&iptables的關系 &#xff08;3&#xff09;firewalld與iptables service的區別 1. ?規則管理方式? 2. ?默認策略與設計邏輯? 3. ?配置文…

JS中實現類似sleep、wait、delay的延時功能

前言 編寫代碼時很多時候需要進行流程化的操作&#xff0c;各個流程間通常需要等待一定時間&#xff0c;這在很多語言中通常可以使用 sleep 、 wait 、 delay 等函數來實現。JavaScript原生并沒有類似的功能&#xff0c;想要延時通常就是使用 setTimeout(functionRef, delay) …

Elasticsearch:使用 ES|QL 進行搜索和過濾

本教程展示了 ES|QL 語法的示例。請參考 Query DSL 版本&#xff0c;以獲得等效的 Query DSL 語法示例。 這是一個使用 ES|QL 進行全文搜索和語義搜索基礎知識的實踐介紹。 有關 ES|QL 中所有搜索功能的概述&#xff0c;請參考《使用 ES|QL 進行搜索》。 在這個場景中&#x…

Java 動態代理實現

Java 動態代理實現 一、JDK動態代理二、CGLIB動態代理三、動態代理的應用場景四、JDK代理與CGLIB代理比較 動態代理是Java中一種強大的技術&#xff0c;它允許在運行時創建代理對象&#xff0c;用于攔截對目標對象的方法調用。 一、JDK動態代理 JDK動態代理是Java標準庫提供的代…

Apache IoTDB V2.0.2/V1.3.4 發布|新增表模型權限管理、UDF、嵌套查詢功能

Release Announcement Version 2.0.2/1.3.4 Apache IoTDB V2.0.2、V1.3.4 已經發布&#xff01; V2.0.2 作為樹表雙模型正式版本&#xff0c;主要新增表模型權限管理、用戶管理以及相關操作鑒權&#xff0c;并新增了表模型 UDF、系統表和嵌套查詢等功能。 V1.3.4 主要新增模式…

鴻蒙開發11-ARKUI框架

ARKUI&#xff08;方舟 UI 框架&#xff09;是 HarmonyOS Next&#xff08;原 OpenHarmony&#xff09;的核心 UI 開發框架&#xff0c;基于聲明式編程范式&#xff0c;支持 ArkTS 語言&#xff0c;能夠高效構建跨設備的響應式應用。以下是對 ARKUI 框架及開發的詳細介紹&#…

Linux 進程間通信詳解

一.進程間通信介紹 1. 進程間通信概念 進程間通信&#xff08;Inter-Process Communication, IPC&#xff09;是指在不同進程之間傳遞或交換信息的一種機制。在操作系統中&#xff0c;進程是資源分配和獨立運行的基本單位&#xff0c;它們擁有各自獨立的內存空間和系統資源。…

從0開始掌握動態規劃

動態規劃的核心思想 -- 以空間換時間 復雜點說通過分解問題為子問題并存儲子問題解來優化復雜計算的算法策略。 簡單看個問題。 一&#xff0c;初始&#xff1a;求最長連續遞增子序列 nums [10,9,2,5,3,7,101,18] 求上面數組中的最長連續遞增子序列&#xff0c;輸出其長度 …

Python Requests 庫:從安裝到精通

摘要 本文詳細介紹 Python Requests 庫的安裝與使用&#xff0c;通過常見示例讓你輕松掌握。 一、引言 在當今的互聯網時代&#xff0c;與各種 Web 服務進行交互是非常常見的需求。Python 作為一門功能強大且易于學習的編程語言&#xff0c;提供了許多用于網絡請求的庫&…

Manus技術架構、實現內幕及分布式智能體項目實戰

Manus技術架構、實現內幕及分布式智能體項目實戰 模塊一&#xff1a; 剖析Manus分布式多智能體全生命周期、九大核心模塊及MCP協議&#xff0c;構建低幻覺、高效且具備動態失敗處理能力的Manus系統。 模塊二&#xff1a; 解析Manus大模型Agent操作電腦的原理與關鍵API&#xf…

C算術運算符 printf輸出格式 字符指針打印輸出 使用scanf函數進行輸入

一 算術運算符 加, 一元取正 - 減, 一元取負 * 乘 / 除 % 求余 -- 自減1 自加1 邏輯運算符 && 邏輯與 || 邏輯或 ! 邏輯非 關系運算符 > 大于 > 大于等于 < 小于 < 小于等于 等于 ! 不等于 位運算符號 & 按位與 | 按位或 ^ 按位異或…

STM32中Hz和時間的轉換

目錄 一、常見的頻率單位及其轉換 二、計算公式 三、STM32中定時器的應用 四、例子 一、常見的頻率單位及其轉換 赫茲&#xff08;Hz&#xff09;是頻率的國際單位&#xff0c;表示每秒鐘周期性事件發生的次數。 1 kHz&#xff08;千赫茲&#xff09; 1,000 Hz1 MHz&#…

《分布式軟總線:不同頻段Wi-Fi環境下設備發現兼容性難題》

分布式軟總線技術作為實現設備互聯互通的關鍵&#xff0c;正逐漸成為構建萬物互聯世界的基石。然而&#xff0c;當分布式軟總線面臨不同頻段Wi-Fi環境時&#xff0c;設備發現的兼容性問題成為了阻礙其廣泛應用的一大挑戰。這一問題不僅影響著用戶體驗&#xff0c;也制約著分布式…

MCP(Model Context Protocol 模型上下文協議)科普

MCP&#xff08;Model Context Protocol&#xff0c;模型上下文協議&#xff09;是由人工智能公司 Anthropic 于 2024年11月 推出的開放標準協議&#xff0c;旨在為大型語言模型&#xff08;LLM&#xff09;與外部數據源、工具及服務提供標準化連接&#xff0c;從而提升AI在實際…

【mongodb】數據庫操作

目錄 1. 查看所有數據庫2. 切換到指定數據庫&#xff08;若數據庫不存在&#xff0c;則創建&#xff09;3. 查看當前使用的數據庫4. 刪除當前數據庫5.默認數據庫 1. 查看所有數據庫 1.show dbs2.show databases 2. 切換到指定數據庫&#xff08;若數據庫不存在&#xff0c;則…

ICPR-2025 | 讓機器人在未知環境中 “聽懂” 指令精準導航!VLTNet:基于視覺語言推理的零樣本目標導航

作者&#xff1a;Congcong Wen, Yisiyuan Huang, Hao Huang ,Yanjia Huang, Shuaihang Yuan, YuHao, HuiLin and Yi Fang 單位&#xff1a;紐約大學阿布扎比分校具身人工智能與機器人實驗室&#xff0c;紐約大學阿布扎比分校人工智能與機器人中心&#xff0c;紐約大學坦登工程…

基于DeepSeek的考研暑假日志分析

注&#xff1a;我去年考研時寫了日志&#xff0c;大致記錄了我每天的主要活動。由于過于瑣碎&#xff0c;一直沒有翻看。突發奇想&#xff0c;現在利用deepseek總結其中規律。 從你的日志中可以總結出以下規律和活動興衰起落&#xff1a; ??一、學習活動規律與演變?? ??…