Chrome插件:網易云音樂聽歌識曲

大家好,我是若川。持續組織了8個月源碼共讀活動,感興趣的可以?點此加我微信ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》?包含20余篇源碼文章。歷史面試系列。另外:目前建有江西|湖南|湖北籍前端群,可加我微信進群。

f650f4db2d216fd16bd560e56996a615.png

當你用網頁在視頻網站刷視頻的時候,有沒有碰到過一個 BGM 激起你內心的波瀾,而你卻不知道它的名字。此時只能打開手機進行聽歌識曲,而通過一個瀏覽器的插件卻更容易解決這個問題。不需要繁瑣的掏出手機,也不會因為需要外放而干擾他人,更不會因為環境噪音而識別困難。

如果你恰好也有這個需要,不妨試一下云音樂出品的 Chrome 瀏覽器插件「云音樂聽歌」[1],還可以直接進行紅心收藏哦。也可以到插件官網[2]預覽實際運行的效果。

背景

目前 Chrome 商店上存在的聽歌識曲插件,大都是國外出品,國內產品寥寥,對于國內音樂支持較差。既然云音樂有這個能力,我們希望將這樣的功能覆蓋每一個角落,傳遞音樂美好力量。與此同時市面上的插件大多還是基于 manifest v2 實現(相對于 manifest v3,安全性、性能、隱私性均較差),普遍的做法是將音頻錄制之后直接交給服務端,通過服務端進行指紋提取,徒增服務端計算壓力,增加網絡傳輸。那么有沒有辦法既能使用 manifest v3 協議進行功能實現,同時將音頻指紋提取這一計算放在前端呢?

Chrome瀏覽器插件新協議

本文的重心不在如何實現一個瀏覽器插件本身,如果你不了解插件本身的開發,可查閱 Google 官方的開發文檔[3]

特別說明的是,manifest v2(MV2) 即將被廢棄,在 2022 年逐步不接受更新,2023 年將會逐步不能運行,本文所有的內容都是基于更安全、性能更好、隱私更強的 manifest v3(MV3)進行實現。

1ebf22dbec39cb112b079ed47b15f206.png

協議升級對功能的實現方式也會帶來一些變化,因為 MV3 更安全的限制,一些基于 MV2 靈活的實現方式(例如:執行遠程代碼、可以使用 eval、new Function(...) 等不安全方法)將不能使用。而這會對聽歌識曲插件帶來一些實現上的難題。

MV3 協議對插件實現核心影響點:

  • 原有的 Background Page 使用 Service Worker 進行替代,這意味著在 Background Page 不再能進行 Web API 等操作。

  • 遠程代碼托管不再支持,無法進行動態加載代碼,意味著可執行的代碼都需要直接打包到插件中。

  • 內容安全策略調整,不再支持不安全代碼的直接執行。WASM 初始化相關函數無法直接運行。

聽歌識曲的實現

聽歌識曲本身技術比較成熟,整體的思路是通過音頻數字采樣,進行音頻指紋的提取,最后將指紋在數據庫進行匹配,特征值最高的即是所認為識別到的歌曲。

8edc738b8de7f2d0098d719eb02c5bef.png

瀏覽器插件中的音頻提取

利用插件進行網頁內的音視頻錄制其實非常簡單,只需要 chrome.tabCapture API 即可實現網頁本身的音頻錄制,獲取到的流數據我們需要針對音頻數據進行采樣,保證計算 HASH 的規則和數據庫數據保持一致。

針對獲取的 stream 流可以進行音頻的轉錄采樣,一般有三種處理方式:

  • createScriptProcessor[4]:此方法用于音頻處理最為簡單,但是此方法已經在 W3C 標準里標記為廢棄。不建議使用

  • MediaRecorder[5]:借助媒體 API 也可以完成音頻的轉錄,但是沒有辦法做到精細處理。

  • AudioWorkletNode[6]:用于替代 createScriptProcessor 進行音頻處理,可以解決同步線程處理導致導致的對主線程的壓力,同時可以按 bit 進行音頻信號處理,這里也選擇此種方式進行音頻采樣。

d707f5f5b051a0c02054753303e4a588.png

基于 AudioWorkletNode 實現音頻的采樣及采樣時長控制方法:

  1. 模塊注冊,這里的模塊加載是通過文件的加載方式,PitchProcessor.js 對應的是根目錄下的文件:

const?audio_ctx?=?new?window.AudioContext({sampleRate:?8000,
});
await?audio_ctx.audioWorklet.addModule("PitchProcessor.js");
  1. 創建 AudioWorkletNode,主要用于接收通過 port.message 從 WebAudio 線程傳遞回來的數據信息,從而可以在主線程進行數據處理:

class?PitchNode?extends?AudioWorkletNode?{//?Handle?an?uncaught?exception?thrown?in?the?PitchProcessor.onprocessorerror(err)?{console.log(`An?error?from?AudioWorkletProcessor.process()?occurred:?${err}`);}init(callback)?{this.callback?=?callback;this.port.onmessage?=?(event)?=>?this.onmessage(event.data);}onmessage(event)?{if?(event.type?===?'getData')?{if?(this.callback)?{this.callback(event.result);}}}
}const?node?=?new?PitchNode(audio_ctx,?"PitchProcessor");
  1. 處理 AudioWorkletProcessor.process,也就是 PitchProcessor.js 文件內容:

process(inputs,?outputs)?{const?inputChannels?=?inputs[0];const?inputSamples?=?inputChannels[0];if?(this.samples.length?<?48000)?{this.samples?=?concatFloat32Array(this.samples,?inputSamples);}?else?{this.port.postMessage({?type:?'getData',?result:?this.samples?});this.samples?=?new?Float32Array(0);}return?true;
}

取第一個輸入通道的第一個聲道進行數字信號的收集,收集到符合定義的長度(例如這里的48000)之后通知到主線程進行信號的識別處理。

基于 process 方法可以做很多有意思的嘗試,比如最基礎的白噪音生成等。

音頻指紋提取

提取到音頻信號之后,下一步要做的就是對信號數據進行指紋提取,我們提取到的其實就是一段二進制數據,需要對數據進行傅里葉變換,轉換為頻域信息進行特征表示。具體指紋的提取的邏輯是有一套規整的復雜算法,常規的指紋提取方法:1) 基于頻帶能量的音頻指紋;2)基于landmark的音頻指紋;3)基于神經網絡的音頻指紋,對算法感興趣的可以閱讀相關論文,例如:A Highly Robust Audio Fingerprinting System[7]。整個運算有一定的性能要求,基于 WebAssembly 進行運算,可以獲得更好的 CPU 性能。現如今,C++/C/Rust 都有比較便捷的方式編譯成 WebAssembly 字節碼,這里不再展開。

接下來,當你嘗試通過在插件場景中運行 WASM 模塊初始化的時候,你大概率會遇到如下異常:

Refused?to?compile?or?instantiate?WebAssembly?module?because?'wasm-eval'?is?not?an?allowed?source?of?script?in?the?following?Content?Security?Policy?directive:?"script-src?'self'?'unsafe-inline'?'unsafe-eval'?...

這是因為在使用 WebAssembly 的時候需要遵循嚴格的 CSP 定義,對于 Chrome MV2 可以通過追加 "content_security_policy":"script-src 'self' 'unsafe-eval';" 進行聲明解決。而在 MV3 中,由于更加嚴格的隱私及安全限制,已經不允許這種簡單粗暴的執行方式了。MV3 中,對于插件頁面 CSP 定義中的script-src object-src worker-src 只允許取值為:

  • self

  • none

  • localhost也就是沒有辦法定義 unsafe-eval 等屬性,所以想單純在插件頁面里直接運行 wasm 已經不可行了。到這似乎已經到了絕路?方法總比問題多,細品文檔,發現文檔有這樣一句描述:

CSP modifications for sandbox have no such new restrictions. —— Chrome插件開發文檔[8]

也就是說這種安全限制在沙盒模式下是沒有的。插件本身可以定義 sandbox[9] 頁面,這種頁面雖然無法訪問 web/chrome API,但是它可以運行一些所謂“不安全”的方法,例如 eval、new Function、WebAssembly.instantiate 等。所以可以借助沙盒頁面進行 WASM 模塊的加載及運行,將計算的結果返回給主頁面,整體的指紋采集的流程就變成,如下圖:

1389d37a9683332066f9af2157080172.png

對于主頁面和沙盒頁面如何進行數據通信,可以通過在主頁面里邊加載 iFrame 的方式,借助iFrame的 contentWindow 和主 window 進行數據聯通,數據流程如下圖:

e7a6703fe4b3605a9151c52a2fe8b320.png

到這里完成了基本的音頻的提取及指紋提取的過程,剩下的部分就是通過指紋在數據庫進行特征匹配。

特征匹配

提取到的音頻指紋后,接下來就是到指紋庫里進行音頻檢索。指紋庫可以用散列表實現,每個表項表示相同指紋對應的音樂ID和音樂出現的時間,構建出指紋數據庫。從數據庫中訪問提取的指紋即可獲取匹配的歌曲。當然這只是一個基本流程,具體的算法優化方式各家還是有很大的差異,除了版權原因,算法直接導致了各家匹配的效率和正確率。而插件這里的實現還是以效率優先的方式。

寫在最后

以上大致描述了基于 WebAssembly 與 MV3實現聽歌識曲插件的大致流程。插件雖然靈活易用,但是 Google 也意識到了插件帶來的一些安全、隱私等問題,從而進行了一次大規模的遷移。MV3 協議更加具備隱私和安全性,但也限制了不少功能的實現,在2023年之后會有大批量的插件無法繼續使用。

關于聽歌識曲插件[10]目前已完成的功能包括音頻識別、紅心歌單收藏等,后續還將繼續功能拓展,希望這個小功能可以幫助到你。

參考資料

  • https://developer.mozilla.org/en-US/[11]

  • https://developer.chrome.com/docs/apps/[12]

  • https://www.w3.org/TR/webaudio/#widl-AudioContext-createScriptProcessor-ScriptProcessorNode-unsigned-long-bufferSize-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels[13]

  • https://developer.mozilla.org/zh-CN/docs/WebAssembly/C_to_wasm[14]

  • http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=152C085A95A4B5EF1E83E9EECC283931?doi=10.1.1.103.2175&rep=rep1&type=pdf[15]

本文發布自網易云音樂技術團隊,文章未經授權禁止任何形式的轉載。我們常年招收各類技術崗位,如果你準備換工作,又恰好喜歡云音樂,那就加入我們 grp.music-fe(at)corp.netease.com!

參考資料見閱讀原文

[1]

「云音樂聽歌」: https://chrome.google.com/webstore/detail/%E4%BA%91%E9%9F%B3%E4%B9%90%E5%90%AC%E6%AD%8C/kemcalcncfhmdkgglekijclbomdoohkp?hl=zh-CN

[2]

插件官網: https://fn.music.163.com/g/chrome-extension-home-page-beta/


07effd8a8e02235099f88c4fc8d0f5e2.gif

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經堅持寫了8年,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助4000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。

2cb4edcddfa21a782456ed3b0d8711d1.png

掃碼加我微信 ruochuan02、拉你進源碼共讀

今日話題

目前建有江西|湖南|湖北?籍 前端群,想進群的可以加我微信 ruochuan12?進群。分享、收藏、點贊、在看我的文章就是對我最大的支持~

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

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

相關文章

五大常用算法之四:回溯法

1、概念 回溯算法實際上一個類似枚舉的搜索嘗試過程&#xff0c;主要是在搜索嘗試過程中尋找問題的解&#xff0c;當發現已不滿足求解條件時&#xff0c;就“回溯”返回&#xff0c;嘗試別的路徑。 回溯法是一種選優搜索法&#xff0c;按選優條件向前搜索&#xff0c;以達到目標…

如何設置ad18捕捉圖標_圖標設計中的像素捕捉

如何設置ad18捕捉圖標More in the iconography series:? Foundations of Iconography? 7 Principles of Icon Design? 5 Ways to Create a Settings Icon? Icon Grids & Keylines Demystified? 3 Classic Icon FamiliesWe all want our designs to display sharp on a…

React Hooks 原理與最佳實踐

大家好&#xff0c;我是若川。持續組織了8個月源碼共讀活動&#xff0c;感興趣的可以 點此加我微信ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列。另外…

BW:BW增量更新方法(假增量)

1 說說假增量 我們都知道&#xff0c;對于BW來說&#xff0c;很多ECC的標準數據源自帶了增量更新功能&#xff0c;每天各種憑證產生的增量數據會自動堆積到增量隊列里&#xff0c;然后BW端做一個增量信息包按天把這些增量抽取到數據倉庫里&#xff0c;非常輕松自然&#xff0c;…

插圖 引用 同一行兩個插圖_為什么插圖是產品的重要組成部分

插圖 引用 同一行兩個插圖“Hi, my name is Ludmila and I’m a UX/UI designer”“嗨&#xff0c;我叫Ludmila&#xff0c;我是UX / UI設計師” “Hi, Ludmila”“嗨&#xff0c;路德米拉” “Welcome”“歡迎” Not anonymously at all, I’ve been doing UX/UI design fo…

如果是你你會如何重新設計和定義維基百科(wikipedia)?

日期&#xff1a;2012-8-11 來源&#xff1a;GBin1.com 最近一家設計公司發布了一個關于如何重新定義和設計維基百科的網站&#xff0c;在這里網站里詳細的刨析了如何重新設計維基百科的話&#xff0c;如何做品牌設計和網站設計&#xff0c;整個設計過程都使用非常詳細的文檔說…

祖父元素_幫助祖父母建立Skype帳戶的UX經驗教訓

祖父元素“Empathy is a key part of a UX designers arsenal”, they say. It’s drilled into our heads that we need to be thinking about our user, about their journey, about what works best for them. And it does feel empowering to boast of empathy, inside vis…

ECSHOP批量添加商品到購物車

Ecshop是一款開源的網上商店系統&#xff0c;在我心目中可以算得上網上商城界的Wordpress了。 本文介紹如何實現在ecshop中批量添加商品到購物車。 大家都知道&#xff0c;默認的ecshop只能單件點擊“添加到購物車”&#xff08;Add to Cart&#xff09;實現一件一件的添加商品…

2022年CSS的發展如何?

大家好&#xff0c;我是若川。持續組織了8個月源碼共讀活動&#xff0c;感興趣的可以 點此加我微信ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列。另外…

分布式實物實現方式_這是您完成實物產品設計任務的方式

分布式實物實現方式You’ve come to the last stages of an interview. There’s only one thing left to do: the dreaded take home design assignment.您已經到達面試的最后階段。 只剩下一件事要做&#xff1a; 可怕的帶回家的設計任務。 This is the hard part of any in…

TP-Link路由器下的多種接入模式

無線AP&#xff1a;把LAN轉成WLAN 客戶端&#xff1a;把WLAN轉成LAN 中繼&#xff1a;簡單放大上一個無線路由器的WLAN信號&#xff0c;SSID與上一個無線路由器一樣 橋接&#xff1a;與上一個無線路由器的WLAN信號連接&#xff0c;SSID與上一個無線路由器不同&#xff0c;又叫W…

type 和 interface 傻傻分不清楚?

大家好&#xff0c;我是若川。持續組織了8個月源碼共讀活動&#xff0c;感興趣的可以 點此加我微信ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列。另外…

上帝公式_感謝上帝的空白

上帝公式Do you ever walk into a room cluttered with discarded papers and leftover takeout and feel comfortable?您是否曾經走進過亂七八糟的房間&#xff1f; Yes, you might if you’re a sophomore at college. That’s just dorm life. Back in the late 90’s to …

POJ 1325 Machine Schedule(二分圖最小點集覆蓋)

題目鏈接&#xff1a;http://poj.org/problem?id1325 題意&#xff1a;A機器有n個模式&#xff0c;B機器有m個模式&#xff0c;有k個任務&#xff0c;第i個任務可以用A機器的ai模式或者B機器的bi模式&#xff0c;換模式需要重啟&#xff0c;開始兩個機器都在模式0&#xff0c;…

figma下載_在Figma上進行原型制作的各種觸發選項

figma下載Prototypes are model versions of digital products. They’re used to measure usability by testing with potential users of a product. When making prototypes with Figma, it is necessary that the actions that trigger reactions aren’t strangers and th…

通過動畫讓你深入理解 ES modules

大家好&#xff0c;我是若川。持續組織了8個月源碼共讀活動&#xff0c;感興趣的可以 點此加我微信ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列。另外…

海量數據處理之倒排索引

前言&#xff1a;本文是對博文http://blog.csdn.net/v_july_v/article/details/7085669的總結和引用 一&#xff0c;什么是倒排索引 問題描述&#xff1a;文檔檢索系統&#xff0c;查詢那些文件包含了某單詞&#xff0c;比如常見的學術論文的關鍵字搜索。 基本原理及要點&#…

ux和ui_如何為您的UX / UI設計選擇正確的原型制作工具

ux和uiAll UX/UI designers might encounter the situation of creating prototypes for wireframes or visual designs. In some cases, you may also receive the need to craft motion designs, for instance, animating icons or illustrations.所有UX / UI設計人員都可能遇…

Vue 性能指標逐漸開始反超 React 了!

大家好&#xff0c;我是若川。持續組織了8個月源碼共讀活動&#xff0c;感興趣的可以 點此加我微信ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列。另外…

制作Ubuntu U 盤啟動盤在ubuntu12.04中

制作U盤啟動盤&#xff0c;這樣就可以通過U盤來裝系統了&#xff0c;簡單便攜。 在Ubuntu下&#xff0c;從dash home中找到Startup disk creator&#xff0c;當然之前把U盤插好&#xff0c;然后很簡單的兩個選擇就好了。 轉載于:https://www.cnblogs.com/allenzhaox/archive/20…