test_mediarecorder_record_audionode.html (4426B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test MediaRecorder Record AudioContext Node</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 7 <script type="text/javascript" src="manifest.js"></script> 8 </head> 9 <body> 10 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968109">Mozilla Bug 968109</a> 11 12 <script class="testbody" type="text/javascript"> 13 14 SimpleTest.waitForExplicitFinish(); 15 16 function setUpSource(contextType, nodeType) { 17 // Use contextType to choose offline or real-time context. 18 const context = contextType == "offline"? 19 new OfflineAudioContext(2 , 80920, 44100) : new AudioContext(); 20 const buffer = context.createBuffer(2, 80920, context.sampleRate); 21 for (let i = 0; i < 80920; ++i) { 22 buffer.getChannelData(0)[i] = Math.sin(1000 * 2 * Math.PI * i / context.sampleRate); 23 buffer.getChannelData(1)[i] = Math.sin(1000 * 2 * Math.PI * i / context.sampleRate); 24 } 25 26 const source = context.createBufferSource(); 27 source.buffer = buffer; 28 source.loop = true; 29 30 source.start(0); 31 32 // nodeType decides which node in graph should be the source of recording. 33 let node; 34 if (nodeType == "source") { 35 node = source; 36 } else if (nodeType == "splitter") { 37 const splitter = context.createChannelSplitter(); 38 source.connect(splitter); 39 node = splitter; 40 } else if (nodeType == "destination") { 41 source.connect(context.destination); 42 node = context.destination; 43 } 44 // Explicitly start offline context. 45 if (contextType == "offline") { 46 context.startRendering(); 47 } 48 49 return node; 50 } 51 52 async function testRecord(source, mimeType) { 53 const isOffline = source.context instanceof OfflineAudioContext; 54 const recorder = new MediaRecorder(source, 0, {mimeType}); 55 is(recorder.mimeType, mimeType, "Mime type is set"); 56 const extendedMimeType = `${mimeType || "audio/ogg"}; codecs=opus`; 57 58 recorder.onwarning = () => ok(false, "should not fire onwarning"); 59 recorder.onerror = () => ok(false, "should not fire onerror"); 60 if (!isOffline) { 61 recorder.onstop = () => ok(false, "should not fire stop yet"); 62 } 63 64 recorder.start(1000); 65 is("recording", recorder.state, "state should become recording after calling start()"); 66 is(recorder.mimeType, mimeType, "Mime type is not changed by start()"); 67 68 await new Promise(r => recorder.onstart = r); 69 is(recorder.mimeType, extendedMimeType, "Mime type is fully defined"); 70 71 const chunks = []; 72 let {data} = await new Promise(r => recorder.ondataavailable = r); 73 if (!isOffline) { 74 is(recorder.state, "recording", "Expected to still be recording"); 75 } 76 is(data.type, extendedMimeType, "Blob has fully defined mimetype"); 77 isnot(data.size, 0, "should get data and its length should be > 0"); 78 chunks.push(data); 79 80 if (isOffline) { 81 await new Promise(r => recorder.onstop = r); 82 is(recorder.state, "inactive", "Offline context should end by itself"); 83 } else { 84 is(recorder.state, "recording", "Expected to still be recording"); 85 recorder.stop(); 86 ({data} = await new Promise(r => recorder.ondataavailable = r)); 87 is(recorder.state, "inactive", "Expected to be inactive after last blob"); 88 isnot(data.size, 0, "should get data and its length should be > 0"); 89 chunks.push(data); 90 91 await new Promise(r => recorder.onstop = r); 92 is(recorder.state, "inactive", "state should remain inactive after stop event"); 93 } 94 return new Blob(chunks, {type: chunks[0].type}); 95 } 96 97 addLoadEvent(async () => { 98 const src = setUpSource(); 99 let didThrow = false; 100 try { 101 new MediaRecorder(src); 102 } catch (e) { 103 didThrow = true; 104 } 105 ok(didThrow, "MediaRecorder(AudioNode) should be hidden behind a pref"); 106 107 await SpecialPowers.pushPrefEnv({set: [ 108 ["media.recorder.audio_node.enabled", true], 109 ]}); 110 111 // Test with various context and source node types. 112 for (const mimeType of [ 113 "audio/ogg", 114 "audio/webm", 115 "video/webm", 116 "", 117 ]) { 118 for (const {context, node} of [ 119 {context: "", node: "source"}, 120 {context: "", node: "splitter"}, 121 {context: "offline", node: "destination"}, 122 ]) { 123 info(`Testing recording ${context || "regular"} context and ${node} ` + 124 `node with mimeType '${mimeType}'`); 125 await testRecord(setUpSource(context, node), mimeType); 126 } 127 } 128 129 SimpleTest.finish(); 130 }); 131 132 </script> 133 </pre> 134 </body> 135 </html>