Documentation Index
Fetch the complete documentation index at: https://docs.qawolf.com/llms.txt
Use this file to discover all available pages before exploring further.
Use Playwright’s getDisplayMedia API with Chrome flags to record audio playing in a browser tab. The recording is saved as a .webm file that can be downloaded and analyzed.
Playwright initializes the fake audio device once per browser instance. You cannot swap audio sources mid-flow. If you need to record different audio content, launch a new browser instance for each.
Examples
Record audio from a browser tab
const { rm } = await import("node:fs/promises");
await rm("/tmp/audioRecording.webm", { force: true });
page.on("download", async (download) => {
await download.saveAs(`/tmp/${download.suggestedFilename()}`);
});
await page.evaluate(async () => {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { displaySurface: "browser" },
audio: { displaySurface: "browser" },
});
const recorder = new MediaRecorder(stream);
window.__rec = recorder;
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: chunks[0]?.type || "video/webm" });
stream.getVideoTracks()[0]?.stop();
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "audioRecording.webm";
document.body.appendChild(a);
a.click();
a.remove();
};
recorder.start();
});
// trigger audio playback in your app
await page.waitForTimeout(10_000);
await page.evaluate(() => window.__rec.stop());
await page.waitForTimeout(10_000);
Download audio from a page element
If your app exposes audio via a <video> or <audio> element, download it directly without screen capture:
const audioUrl = await page.locator("video").getAttribute("src");
const [download] = await Promise.all([
page.waitForEvent("download"),
page.evaluate((url) => {
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "audio.m4a");
document.body.appendChild(link);
link.click();
link.remove();
}, audioUrl),
]);
const filePath = await download.path();
When to use
- Your app streams or plays audio and you need to verify the correct audio played.
- Your app generates audio output and you need to capture it for analysis.
- Your test needs to validate audio content that can’t be asserted through the UI.
- Your app has a media player and you need to confirm playback works end to end.
Full sample test
import { flow, launch } from "@qawolf/flows/web";
export default flow(
"Record browser audio",
"Web - Chrome",
async ({ test }) => {
const { context } = await launch({
permissions: ["microphone", "camera", "clipboard-read", "clipboard-write"],
args: [
"--enable-experimental-web-platform-features",
"--use-fake-device-for-media-stream",
"--use-fake-ui-for-media-stream",
"--enable-usermedia-screen-capturing",
"--auto-select-desktop-capture-source=Entire screen",
],
});
const page = await context.newPage();
await test("record audio and verify file was captured", async () => {
// Arrange
await page.goto("https://your-app.com/player");
await page.locator(`[data-testid='play-button']`).waitFor({ state: "visible" });
const { rm, access } = await import("node:fs/promises");
await rm("/tmp/audioRecording.webm", { force: true });
page.on("download", async (download) => {
await download.saveAs(`/tmp/${download.suggestedFilename()}`);
});
await page.evaluate(async () => {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { displaySurface: "browser" },
audio: { displaySurface: "browser" },
});
const recorder = new MediaRecorder(stream);
window.__rec = recorder;
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: chunks[0]?.type || "video/webm" });
stream.getVideoTracks()[0]?.stop();
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "audioRecording.webm";
document.body.appendChild(a);
a.click();
a.remove();
};
recorder.start();
});
// Act
await page.locator(`[data-testid='play-button']`).click();
await page.waitForTimeout(10_000);
await page.evaluate(() => window.__rec.stop());
await page.waitForTimeout(10_000);
// Assert
async function exists(p) {
try { await access(p); return true; } catch { return false; }
}
expect(await exists("/tmp/audioRecording.webm")).toBeTruthy();
});
},
);