fix: bilibili音源无法播放的问题 (#1573)

master
memorydream 3 years ago committed by GitHub
parent 93ae57adbe
commit c85af59b21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -88,10 +88,10 @@ function toBuffer(data) {
} }
/** /**
* Get the file URI from bilivideo. * Get the file base64 data from bilivideo.
* *
* @param {string} url The URL to fetch. * @param {string} url The URL to fetch.
* @returns {Promise<string>} The file URI. * @returns {Promise<string>} The file base64 data.
*/ */
async function getBiliVideoFile(url) { async function getBiliVideoFile(url) {
const axios = await import('axios').then(m => m.default); const axios = await import('axios').then(m => m.default);
@ -106,7 +106,7 @@ async function getBiliVideoFile(url) {
const buffer = toBuffer(response.data); const buffer = toBuffer(response.data);
const encodedData = buffer.toString('base64'); const encodedData = buffer.toString('base64');
return `data:application/octet-stream;base64,${encodedData}`; return encodedData;
} }
/** /**

@ -10,6 +10,7 @@ import { cacheTrackSource, getTrackSource } from '@/utils/db';
import { isCreateMpris, isCreateTray } from '@/utils/platform'; import { isCreateMpris, isCreateTray } from '@/utils/platform';
import { Howl, Howler } from 'howler'; import { Howl, Howler } from 'howler';
import shuffle from 'lodash/shuffle'; import shuffle from 'lodash/shuffle';
import { decode as base642Buffer } from '@/utils/base64';
const PLAY_PAUSE_FADE_DURATION = 200; const PLAY_PAUSE_FADE_DURATION = 200;
@ -329,25 +330,27 @@ export default class {
} }
this.setOutputDevice(); this.setOutputDevice();
} }
_getAudioSourceFromCache(id) { _getAudioSourceBlobURL(data) {
return getTrackSource(id).then(t => { // Create a new object URL.
if (!t) return null; const source = URL.createObjectURL(new Blob([data]));
// Create a new object URL.
const source = URL.createObjectURL(new Blob([t.source]));
// Clean up the previous object URLs since we've created a new one. // Clean up the previous object URLs since we've created a new one.
// Revoke object URLs can release the memory taken by a Blob, // Revoke object URLs can release the memory taken by a Blob,
// which occupied a large proportion of memory. // which occupied a large proportion of memory.
for (const url in this.createdBlobRecords) { for (const url in this.createdBlobRecords) {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
} }
// Then, we replace the createBlobRecords with new one with // Then, we replace the createBlobRecords with new one with
// our newly created object URL. // our newly created object URL.
this.createdBlobRecords = [source]; this.createdBlobRecords = [source];
return source; return source;
}
_getAudioSourceFromCache(id) {
return getTrackSource(id).then(t => {
if (!t) return null;
return this._getAudioSourceBlobURL(t.source);
}); });
} }
_getAudioSourceFromNetease(track) { _getAudioSourceFromNetease(track) {
@ -416,15 +419,26 @@ export default class {
); );
if (store.state.settings.automaticallyCacheSongs && retrieveSongInfo?.url) { if (store.state.settings.automaticallyCacheSongs && retrieveSongInfo?.url) {
cacheTrackSource( // 对于来自 bilibili 的音源
track, // retrieveSongInfo.url 是音频数据的base64编码
retrieveSongInfo.url, // 其他音源为实际url
128000, const url =
`unm:${retrieveSongInfo.source}` retrieveSongInfo.source === 'bilibili'
); ? `data:application/octet-stream;base64,${retrieveSongInfo.url}`
: retrieveSongInfo.url;
cacheTrackSource(track, url, 128000, `unm:${retrieveSongInfo.source}`);
}
if (!retrieveSongInfo) {
return null;
}
if (retrieveSongInfo.source !== 'bilibili') {
return retrieveSongInfo.url;
} }
return retrieveSongInfo?.url; const buffer = base642Buffer(retrieveSongInfo.url);
return this._getAudioSourceBlobURL(buffer);
} }
_getAudioSource(track) { _getAudioSource(track) {
return this._getAudioSourceFromCache(String(track.id)) return this._getAudioSourceFromCache(String(track.id))

@ -0,0 +1,67 @@
// https://github.com/niklasvh/base64-arraybuffer/blob/master/src/index.ts
// Copyright (c) 2012 Niklas von Hertzen Licensed under the MIT license.
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// Use a lookup table to find the index.
const lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);
for (let i = 0; i < chars.length; i++) {
lookup[chars.charCodeAt(i)] = i;
}
export const encode = arraybuffer => {
let bytes = new Uint8Array(arraybuffer),
i,
len = bytes.length,
base64 = '';
for (i = 0; i < len; i += 3) {
base64 += chars[bytes[i] >> 2];
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64 += chars[bytes[i + 2] & 63];
}
if (len % 3 === 2) {
base64 = base64.substring(0, base64.length - 1) + '=';
} else if (len % 3 === 1) {
base64 = base64.substring(0, base64.length - 2) + '==';
}
return base64;
};
export const decode = base64 => {
let bufferLength = base64.length * 0.75,
len = base64.length,
i,
p = 0,
encoded1,
encoded2,
encoded3,
encoded4;
if (base64[base64.length - 1] === '=') {
bufferLength--;
if (base64[base64.length - 2] === '=') {
bufferLength--;
}
}
const arraybuffer = new ArrayBuffer(bufferLength),
bytes = new Uint8Array(arraybuffer);
for (i = 0; i < len; i += 4) {
encoded1 = lookup[base64.charCodeAt(i)];
encoded2 = lookup[base64.charCodeAt(i + 1)];
encoded3 = lookup[base64.charCodeAt(i + 2)];
encoded4 = lookup[base64.charCodeAt(i + 3)];
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
}
return arraybuffer;
};

@ -301,23 +301,6 @@
</div> </div>
</div> </div>
<div class="item">
<div class="left">
<div class="title"> 请求用代理服务器 (Proxy) </div>
<div class="description">
请求如 YouTube 音源服务时要使用的代理服务器<br />
留空则不进行相关设置
</div>
</div>
<div class="right">
<input
v-model="unmProxyUri"
class="text-input margin-right-0"
placeholder="例 https://192.168.11.45"
/>
</div>
</div>
<div class="item"> <div class="item">
<div class="left"> <div class="left">
<div class="title"> Joox 引擎的 Cookie </div> <div class="title"> Joox 引擎的 Cookie </div>

Loading…
Cancel
Save