#javascript #arrays
#javascript #массивы
Вопрос:
Чтобы улучшить свои навыки программирования и изучить propouse, я пишу расширение для Chrome, которое будет перехватывать трафик из open.spotify.com Моя задача — получить доступ к воспроизводимой дорожке и сохранить ее в виде аудиофайла на ПК. На данный момент я нашел xmlhttprequest, который будет обслуживать треки при нажатии кнопки воспроизведения, я использую API выборки URL для получения большого двоичного объекта, содержащего фрагмент с этим кодом
const createChunksFromStream = (details) => {
const chunkUrl = details.url;
fetch(chunkUrl)
.then( (res) => res.arrayBuffer() )
.then( (res) => {
console.log(res);
blobChunks.push(res);
});
}
Это даст мне ArrayBuffer (я также пробовал с blob), который будет иметь такую структуру
ArrayBuffer(4749932)
[[Int8Array]]: Int8Array(4749932) [0, 0, 0, 24, 102, 116, 121, 112, 100, 97, 115, 104, 0, 0, 0, 0, 105, 115, 111, 54, 109, 112, 52, 49, 0, 0, 3, -62, 109, 111, 111, 118, 0, 0, 0, 108, 109, 118, 104, 100, 0, 0, 0, 0, -45, -116, 22, 32, -45, -116, 22, 32, 0, 0, -84, 68, 0, -67, -55, 52, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, …]
[[Int16Array]]: Int16Array(2374966) [0, 6144, 29798, 28793, 24932, 26739, 0, 0, 29545, 13935, 28781, 12596, 0, -15869, 28525, 30319, 0, 27648, 30317, 25704, 0, 0, -29485, 8214, -29485, 8214, 0, 17580, -17152, 13513, 256, 0, 1, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512, 0, -31232, 25965, 24948, 0, 0, 0, 8192, 25704, 29292, 0, 0, 0, 0, 17481, 12851, 0, 0, 0, 0, 0, 0, 0, 23040, 17481, 12851, 0, 0, -14571, 17481, …]
[[Int32Array]]: Int32Array(1187483) [402653184, 1887007846, 1752392036, 0, 913273705, 825520237, -1039990784, 1987014509, 1811939328, 1684567661, 0, 538348755, 538348755, 1152122880, 885636352, 256, 1, 0, 0, 256, 0, 0, 0, 256, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 33554432, -2046820352, 1635018093, 0, 536870912, 1919706216, 0, 0, 842220617, 0, 0, 0, 1509949440, 842220617, 0, 1145685781, 1075, 1107296256, 1447645776, 939524096, 1952972800, 980643956, 1768369967, 1651861620, 1836016430, 1869571887, 795176039, 1935762533, 1634741608, 1734437731, 889221733, 892416308, 1915565922, 1634036837, 25971, 1986869248, 30821, 1701646336, 25704, -1124073472, 13513, 1920212992, 30821, 0, 256, 256, 4, 0, 0, 1920220418, 27489, 1802787840, 25704, -1932328192, -1932320746, 8214, 256, -1124073472, 13513, 0, 0, 65536, 16777216, 0, 0, 0, …]
[[Uint8Array]]: Uint8Array(4749932) [0, 0, 0, 24, 102, 116, 121, 112, 100, 97, 115, 104, 0, 0, 0, 0, 105, 115, 111, 54, 109, 112, 52, 49, 0, 0, 3, 194, 109, 111, 111, 118, 0, 0, 0, 108, 109, 118, 104, 100, 0, 0, 0, 0, 211, 140, 22, 32, 211, 140, 22, 32, 0, 0, 172, 68, 0, 189, 201, 52, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, …]
byteLength: (...)
Я помещаю каждую извлеченную часть трека в массив, а затем пытаюсь объединить все в аудиофайл.
const processChunks = async (blobChunks) => {
console.log('chunk stream log', blobChunks);
//let audioBuffer = [];
//blobChunks.forEach( (chunk) => {
//let wav = new lamejs.WavHeader.readHeader(new DataView(chunk));
//console.log(wav);
//let sample = new Int16Array(chunk, wav.dataOffset, wav.dataLen / 2);
for(var i = 0; i < blobChunks.length; i ){
//let sampleChunk = blobChunks[i]["[[Int16Array]]"];
let mp3buf = mp3encoder.encodeBuffer(blobChunks[i]);
if(mp3buf.length > 0){
mp3Data.push(mp3buf);
}
}
//})
// see if there's any data left
let mp3buf = mp3encoder.flush();
if(mp3buf.length > 0){
mp3Data.push(mp3buf);
}
const output = new Blob([mp3Data], {type: 'audio/mp3'});
const fileURL = URL.createObjectURL(output);
chrome.downloads.download({
saveAs: true,
url: fileURL
}, (downloadId) => {
console.log(downloadId);
URL.revokeObjectURL(fileURL);
});
}
Основная проблема, с которой я сталкиваюсь, заключается в том, как я могу объединить фрагменты, я попытался открыть одну ссылку, и она загрузит аудиофайл, но на несколько секунд, если длина, например, 3 МБ. Я пробовал использовать библиотеку lamejs, но безуспешно.
После проверки details
объекта, предоставленного из webRequest.onCompleted
, я могу видеть, что каждый запрос на выборку для фрагментов содержит некоторую информацию о заголовках, подобную этой
{frameId: 0, fromCache: false, initiator: "https://open.spotify.com", ip: "2.23.155.163", method: "GET", …}
frameId: 0
fromCache: false
initiator: "https://open.spotify.com"
ip: "2.23.155.163"
method: "GET"
parentFrameId: -1
requestId: "34278"
responseHeaders: Array(15)
0: {name: "Last-Modified", value: "Mon, 11 Nov 2019 15:09:43 GMT"}
1: {name: "ETag", value: ""9bea6e72675dd37c95f3912cbad4fa3b""}
2: {name: "Content-Type", value: "application/octet-stream"}
3: {name: "Accept-Ranges", value: "bytes"}
4: {name: "Cache-Control", value: "no-transform, max-age=10423291"}
5: {name: "Cache-Control", value: "max-age=315360000, no-transform"}
6: {name: "Date", value: "Sun, 03 Jan 2021 17:44:26 GMT"}
7: {name: "Connection", value: "keep-alive"}
8: {name: "Access-Control-Max-Age", value: "86400"}
9: {name: "Access-Control-Allow-Headers", value: "range, pragma, cache-control"}
10: {name: "Access-Control-Allow-Methods", value: "GET"}
11: {name: "Access-Control-Allow-Origin", value: "*"}
12: {name: "Expires", value: "Wed, 01 Jan 2031 17:44:26 GMT"}
13:
name: "Content-Range"
value: "bytes 495280-660808/4825768"
__proto__: Object
14:
name: "Content-Length"
value: "165529"
__proto__: Object
length: 15
__proto__: Array(0)
statusCode: 206
statusLine: "HTTP/1.1 206 Partial Content"
tabId: 127
timeStamp: 1609695866818.061
type: "xmlhttprequest"
...
Я думаю получить только запрос с кодом состояния 206 и использовать значение Content-Range
заголовка, чтобы проверить, загружены ли все фрагменты, но я не уверен в этом, я думаю также получить только тело каждого отдельного запроса, используя webRequest
, но я не знаю, как и возможно ли это.
Есть ли какое-либо решение, которое я могу использовать для объединения файлов и получения полной звуковой дорожки?