<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                在[上一篇](https://juejin.im/post/5d453bc3e51d4561e36ad9f1)文章中,我們已經獲取到所有的"完整"音頻段落,接下來就要利用這些"完整"的音頻段落,進行音頻分段加載的**最后兩步操作**: 4. wavesurfer 處理之前獲取到的每一小段的 buffer 產生每一小段的波形信息 5. 當wav資源的所有字節都被請求到,并且 buffer 也都被 wavesurfer 處理完畢成波形信息,拼接所有請求段的波形信息,交給 wavesurfer 進行渲染,在渲染的同時,生成波形信息文件上傳到服務端保存,下次再獲取相同的wav資源就直接獲取波形信息文件,避免重復的 decode #### 如何讓 wavesurfer 擁有只產生波形信息的能力 wavesurfer 是沒有想外提供一個產出波形信息 Peaks 的方法的,所以就需要一點點技巧~ ~~~ /** * Get the correct peaks for current wave view-port and render wave * * @private * @emits WaveSurfer#redraw */ drawBuffer() { const nominalWidth = Math.round( this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio ); const parentWidth = this.drawer.getWidth(); let width = nominalWidth; // always start at 0 after zooming for scrolling : issue redraw left part let start = 0; let end = Math.max(start + parentWidth, width); // Fill container if ( this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth) ) { width = parentWidth; start = 0; end = width; } let peaks; if (this.params.partialRender) { /* something */ } else { peaks = this.backend.getPeaks(width, start, end); this.drawer.drawPeaks(peaks, width, start, end); } this.fireEvent('redraw', peaks, width); } 復制代碼 ~~~ 以上代碼來自 [wavesurfer github 源碼](https://github.com/katspaugh/wavesurfer.js/blob/832e114b7be6436458fc351a57699ba169d08676/src/wavesurfer.js#L1130-L1183),可以看到的是 wavesurfer 在 draweBuffer 過程中得到當前正確的 peaks 信息,是根據當前的渲染容器寬度、minPxPerSec、pixelRatio和資源時長來控制 getPeaks 方法的 width、start、end參數,然后調用 drawer 的 drawPeaks 方法繪制。 根據以上分析以及我們的需求僅僅是得到 peaks 波形信息,所以我們需要借用上面的代碼擴展一下 wavesurfer 方法: ~~~ // 擴展到 WaveSurfer 構造器中方法 // 每一段音頻 buffer 產生 peaks 方法 getPeaks(arraybuffer, callback) { this.backend.decodeArrayBuffer( arraybuffer, buffer => { if (!this.isDestroyed) { // https://github.com/katspaugh/wavesurfer.js/blob/832e114b7be6436458fc351a57699ba169d08676/src/wavesurfer.js#L1395-L1396 // decodeArrayBuffer 之后的一個賦值、置空操作。完全模仿 this.backend.buffer = buffer; this.backend.setPeaks(null); const nominalWidth = Math.round( this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio ); const parentWidth = this.drawer.getWidth(); let width = nominalWidth; let start = 0; // 此處謹記 end 一定要賦值為 width // 原本的 let end = Math.max(start + parentWidth, width) 是比較了容器寬度和根據音頻時長等計算出的長度,取最大值。 // 那么會在當前的音頻分段時長大小(例子是2M音頻的時長)所能產生的波形長度小于容器的寬度時 // 出現為了充滿容器下面的 this.backend.getPeaks 方法在實際產生的波形信息后面添加不等位數的 0,從而充滿容器。 // 但是整個大音頻的時長是固定的,根據大音頻時長設定的canvas的個數和寬度已經固定 // 如果分段加載之后最后一段如果出現被補0的情況,在最終合并的完整的波形信息就會超過原本設定的預值,導致擠壓最終產生的波形 let end = width; if ( this.params.fillParent && (!this.params.scrollParent || nominalWidth < parentWidth) ) { width = parentWidth; } const peaks = this.backend.getPeaks(width, start, end); // 通過回調函數的方式把 peaks 傳遞出去 callback(peaks); // 清空 arraybuffer 避免占用過多內存 this.arraybuffer = null; this.backend.buffer = null; } }, () => this.fireEvent('error', 'Error decoding audiobuffer') ); } // 加載所有的波形信息產生可視化canvas loadPeaks(peaks) { this.backend.buffer = null; this.backend.setPeaks(peaks); this.drawBuffer(); this.fireEvent('waveform-ready'); this.isReady = true; } 復制代碼 ~~~ 增強了 wavesurfer 的能力之后就需要在業務中調用了~~ #### 調用擴展能力,整合波形信息,渲染并上傳保存 ~~~ import _ from 'lodash'; import pako from 'pako'; // JS壓縮以及解壓縮三方庫 import WaveSurfer from 'wavesurfer.js'; import requestWav from 'requestWav'; const waveSurfer = null; const peaksList = []; const texture = null; function initWaveSurfer() { const options = { container: '#waveform', backend: 'MediaElement', fillParent: false, // 重要 height: 200, barHeight: 10, normalize: true, minPxPerSec: 100, } waveSurfer = WaveSurfer.create(options); renderWaveSurfer(); } function renderWaveSurfer() { waveSurfer.load(source, [], 'none'); if (!texture) { decodePeaks(); } } function decodePeaks() { const that = this; requestWav.loadBlocks('音頻Url', { loadRangeSucess(data, index) { // 每一段加載完成之后的回調 peaksList[index - 1] = []; // 調用擴展的 waveSurfer 方法獲取每一段音頻的 peaks waveSurfer.getPeaks(data, (peaks) => { peaksList[index - 1] = peaks; }); }, loadAllSucess() { // 所有都加載完之后的回調 let texture = _.flatten(peaksList); // peaksList 降維 if (!texture) { return; } // 按照一定等級進行壓縮 (減少傳輸時間,但是同時需要之后在下載使用波形信息的時候解壓) waveSurfer.texture = pako.deflate(JSON.stringify(texture), { level: 9, to: 'string' }); // 解壓和壓縮的方法是相反的 // const texture = pako.deflate(JSON.stringify(waveSurfer.texture), { level: 9, to: 'string' }); // 手動置空變量, 避免占用內存過大 texture = null; // 創建上傳 FormData const peaksFile = new FormData(); peaksFile.append('sourceUrl', 音頻的URL地址); // 創建上傳文件 Blob const blob = new Blob([waveSurfer.texture], { type: 'application/json' }); // 賦值文件名、文件內容 peaksFile.append('sourcePeaks', blob, 'sourcePeaks'); axios({ method: 'post', url: '上傳地址', data: peaksFile, headers: { 'Content-Type': 'multipart/form-data', }, timeout: 1000000, // 防止文件過大上傳超時,當然不設置也可 }); }, }); } 復制代碼 ~~~ 至此 5個步驟全部完成,剩下的只有在二次請求相同資源的時候判斷如果已經存儲了當前wav資源的波形信息就不用再一次執行一次 decode 產生波形的操作。 作者:ThoughtZer 鏈接:https://juejin.im/post/5d481cf25188250586752b22 來源:掘金 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看