Skip to content

Commit dc11e40

Browse files
author
hoang.tran12
committed
ye it work
1 parent 7201052 commit dc11e40

File tree

3 files changed

+101
-141
lines changed

3 files changed

+101
-141
lines changed

scripts/_test.js

Lines changed: 25 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,100 +9,47 @@ export default {
99
vi: "",
1010
},
1111

12+
// record audio when have stream: https://stackoverflow.com/a/34919194/23648002
13+
// https://www.youtube.com/watch?v=uk96O7N1Yo0
14+
// https://www.skilldrick.co.uk/fft/
15+
// https://stackoverflow.com/a/61301293/23648002
16+
// https://www.renderforest.com/music-visualisations
17+
// https://developer.chrome.com/docs/extensions/reference/api/tabCapture#preserving-system-audio
18+
// https://github.com/Douile/Chrome-Audio-Visualizer/tree/master
19+
// https://stackoverflow.com/questions/66217882/properly-using-chrome-tabcapture-in-a-manifest-v3-extension
20+
// https://groups.google.com/a/chromium.org/g/chromium-extensions/c/ffI0iNd79oo
1221
// https://github.dev/GoogleChrome/chrome-extensions-samples/api-samples/tabCapture
1322

1423
onClickContentScript: async () => {
1524
try {
16-
const tab = await UfsGlobal.Extension.runInBackground(
17-
"utils.getCurrentTab"
25+
const currentTabId = await UfsGlobal.Extension.runInBackground(
26+
"utils.getCurrentTabId"
1827
);
1928

20-
const streamId = await UfsGlobal.Extension.runInBackground(
21-
"chrome.desktopCapture.chooseDesktopMedia",
22-
[["tab", "audio"], tab, "callback"]
29+
const url = await UfsGlobal.Extension.getURL("/scripts/_test.html");
30+
const { tabs } = await UfsGlobal.Extension.runInBackground(
31+
"chrome.windows.create",
32+
[{ url, height: 400, width: 800 }]
2333
);
34+
const tab = tabs[0];
2435

25-
navigator.webkitGetUserMedia(
26-
{
27-
audio: {
28-
mandatory: {
29-
chromeMediaSource: "tab",
30-
chromeMediaSourceId: streamId,
31-
},
32-
},
33-
},
34-
function (stream) {
35-
const context = new AudioContext();
36-
const source = context.createMediaStreamSource(stream);
37-
const analyser = context.createAnalyser();
38-
source.connect(analyser);
39-
source.connect(context.destination);
40-
analyser.connect(context.destination);
41-
},
42-
function (error) {
43-
alert("no");
44-
console.log(error);
45-
}
46-
);
47-
} catch (e) {
48-
console.log(e);
49-
}
50-
},
51-
52-
_onClickContentScript: async () => {
53-
// https://developer.chrome.com/docs/extensions/reference/api/tabCapture#preserving-system-audio
54-
// https://github.com/Douile/Chrome-Audio-Visualizer/tree/master
55-
// https://stackoverflow.com/questions/66217882/properly-using-chrome-tabcapture-in-a-manifest-v3-extension
56-
// https://groups.google.com/a/chromium.org/g/chromium-extensions/c/ffI0iNd79oo
36+
await UfsGlobal.Extension.runInBackground("utils.waitForTabToLoad", [
37+
tab.id,
38+
]);
5739

58-
try {
59-
const tab = await UfsGlobal.Extension.runInBackground(
60-
"utils.getCurrentTab"
61-
);
62-
63-
const streamId = await UfsGlobal.Extension.runInBackground(
64-
"chrome.tabCapture.getMediaStreamId",
65-
[
66-
{
67-
targetTabId: tab.id,
68-
consumerTabId: tab.id,
69-
},
70-
]
71-
);
72-
73-
navigator.webkitGetUserMedia(
40+
UfsGlobal.Extension.runInBackground("chrome.tabs.sendMessage", [
41+
tab.id,
7442
{
75-
audio: {
76-
mandatory: {
77-
chromeMediaSource: "tab",
78-
chromeMediaSourceId: streamId,
79-
},
80-
},
81-
},
82-
function (stream) {
83-
const context = new AudioContext();
84-
const source = context.createMediaStreamSource(stream);
85-
const analyser = context.createAnalyser();
86-
source.connect(analyser);
87-
source.connect(context.destination);
88-
analyser.connect(context.destination);
43+
targetTabId: currentTabId,
44+
consumerTabId: tab.id,
8945
},
90-
function (error) {
91-
alert("no");
92-
console.log(error);
93-
}
94-
);
46+
]);
9547
} catch (e) {
96-
alert(e);
48+
console.log(e);
9749
}
9850
},
9951

10052
onClick_: async () => {
101-
//https://www.youtube.com/watch?v=uk96O7N1Yo0
102-
// https://www.skilldrick.co.uk/fft/
103-
// https://stackoverflow.com/a/61301293/23648002
104-
// https://www.renderforest.com/music-visualisations
105-
10653
javascript: (function () {
10754
var ctx;
10855
var width = 1000;
@@ -330,5 +277,3 @@ export default {
330277
})();
331278
},
332279
};
333-
334-
// record audio when have stream: https://stackoverflow.com/a/34919194/23648002

scripts/_test_main.js

Lines changed: 65 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,72 @@
1-
window.onload = () => {
2-
let streamId;
3-
let interval = setInterval(() => {
4-
streamId = localStorage.getItem("streamId");
5-
if (streamId) {
6-
clearInterval(interval);
7-
setStreamId(streamId);
8-
}
9-
}, 500);
10-
};
1+
chrome.runtime.onMessage.addListener(function (request) {
2+
const { targetTabId, consumerTabId } = request;
3+
testGetMediaStreamId(targetTabId, consumerTabId);
4+
});
115

12-
function setStreamId(streamId) {
13-
navigator.mediaDevices
14-
.getUserMedia({
15-
audio: {
16-
mandatory: {
17-
chromeMediaSource: "tab",
18-
chromeMediaSourceId: streamId,
6+
function testGetMediaStreamId(targetTabId, consumerTabId) {
7+
chrome.tabCapture.getMediaStreamId(
8+
{ targetTabId, consumerTabId },
9+
function (streamId) {
10+
if (!streamId) return;
11+
navigator.webkitGetUserMedia(
12+
{
13+
audio: {
14+
mandatory: {
15+
chromeMediaSource: "tab", // The media source must be 'tab' here.
16+
chromeMediaSourceId: streamId,
17+
},
18+
},
19+
video: false,
20+
},
21+
function (stream) {
22+
draw(stream);
1923
},
20-
},
21-
})
22-
.then((tabStream) => {
23-
// at this point the sound of the tab becomes muted with no way to unmute it
24-
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
25-
const source = audioCtx.createMediaStreamSource(tabStream);
26-
const analyser = audioCtx.createAnalyser();
27-
analyser.fftSize = 2048;
28-
const bufferLength = analyser.frequencyBinCount;
29-
const dataArray = new Uint8Array(bufferLength);
30-
source.connect(analyser);
31-
analyser.connect(audioCtx.destination);
24+
function (error) {
25+
console.error(error);
26+
}
27+
);
28+
}
29+
);
30+
}
3231

33-
const canvas = document.createElement("canvas");
34-
canvas.width = 800;
35-
canvas.height = 200;
36-
canvas.style.cssText =
37-
"position: fixed; top: 0; left: 0; z-index: 2147483647; background: #333a;";
38-
document.body.appendChild(canvas);
39-
const canvasCtx = canvas.getContext("2d");
32+
function draw(stream) {
33+
// at this point the sound of the tab becomes muted with no way to unmute it
34+
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
35+
const source = audioCtx.createMediaStreamSource(stream);
36+
const analyser = audioCtx.createAnalyser();
37+
analyser.fftSize = 2048;
38+
const bufferLength = analyser.frequencyBinCount;
39+
const dataArray = new Uint8Array(bufferLength);
40+
source.connect(analyser);
41+
analyser.connect(audioCtx.destination);
4042

41-
function draw() {
42-
analyser.getByteFrequencyData(dataArray);
43-
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
44-
canvasCtx.beginPath();
45-
const barWidth = ~~(bufferLength / canvas.width);
46-
for (let x = 0; x < canvas.width; x++) {
47-
let i = x * barWidth;
48-
let item = dataArray[i];
49-
const barHeight = map(item, 0, 255, 0, canvas.height);
50-
canvasCtx.lineTo(x, canvas.height - barHeight);
51-
}
52-
canvasCtx.strokeStyle = "rgba(255, 255, 255, 0.9)";
53-
canvasCtx.stroke();
54-
requestAnimationFrame(draw);
55-
}
43+
const canvas = document.createElement("canvas");
44+
canvas.width = 800;
45+
canvas.height = 200;
46+
canvas.style.cssText =
47+
"position: fixed; top: 0; left: 0; z-index: 2147483647; background: #333a;";
48+
document.body.appendChild(canvas);
49+
const canvasCtx = canvas.getContext("2d");
50+
51+
function draw() {
52+
analyser.getByteFrequencyData(dataArray);
53+
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
54+
canvasCtx.beginPath();
55+
const barWidth = ~~(bufferLength / canvas.width);
56+
for (let x = 0; x < canvas.width; x++) {
57+
let i = x * barWidth;
58+
let item = dataArray[i];
59+
const barHeight = map(item, 0, 255, 0, canvas.height);
60+
canvasCtx.lineTo(x, canvas.height - barHeight);
61+
}
62+
canvasCtx.strokeStyle = "rgba(255, 255, 255, 0.9)";
63+
canvasCtx.stroke();
64+
requestAnimationFrame(draw);
65+
}
5666

57-
function map(x, in_min, in_max, out_min, out_max) {
58-
return (
59-
((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
60-
);
61-
}
67+
function map(x, in_min, in_max, out_min, out_max) {
68+
return ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min;
69+
}
6270

63-
requestAnimationFrame(draw);
64-
})
65-
.catch((e) => {
66-
console.log("ERROR", e);
67-
});
71+
requestAnimationFrame(draw);
6872
}

scripts/helpers/utils.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
const { version } = chrome.runtime?.getManifest() || {};
44

5+
export function waitForTabToLoad(tabId) {
6+
return new Promise((resolve) => {
7+
chrome.tabs.onUpdated.addListener(function listener(_tabId, info) {
8+
if (tabId === _tabId && info.status === "complete") {
9+
chrome.tabs.onUpdated.removeListener(listener);
10+
resolve();
11+
}
12+
});
13+
});
14+
}
15+
516
export function runFunc(fnPath = "", params = [], global = {}) {
617
return new Promise((resolve) => {
718
let fn = fnPath?.startsWith("chrome") ? chrome : global;

0 commit comments

Comments
 (0)