- From: guest271314 via GitHub <sysbot+gh@w3.org>
- Date: Fri, 21 Aug 2020 01:44:04 +0000
- To: public-webrtc-logs@w3.org
One way to solve this is `fetch('url').then(r => r.mediaStream())` and `fetch('url').then(r => r.mediaStreamTrack())` Proof-of-concept ``` <?php if (isset($_GET["start"])) { header("Access-Control-Allow-Origin: *"); header("Content-Type: application/octet-stream"); echo passthru("parec -v --raw -d alsa_output.pci-0000_00_1b.0.analog-stereo.monitor"); exit(); } ``` ``` <doctype html> <html> <body> <button>start</button><button>stop</button> <script> if (globalThis.gc) { // gc(); } let controller, signal; // throws memory allocation error, use multiple Memory instances // const memory = new WebAssembly.Memory({initial: 8062, maximum: 9675, shared: true}); const [start, stop] = document.querySelectorAll('button'); start.onclick = async e => { class AudioWorkletProcessor {} class AudioWorkletNativeFileStream extends AudioWorkletProcessor { constructor(options) { super(options); this.byteSize = 512 * 344 * 60 * 50; this.memory = new Uint8Array(this.byteSize); Object.assign(this, options.processorOptions); this.port.onmessage = this.appendBuffers.bind(this); } async appendBuffers({ data: readable }) { Object.assign(this, { readable }); const source = { write: (value, c) => { if (this.totalBytes < this.byteSize) { this.memory.set(value, this.readOffset); this.readOffset = this.readOffset + value.buffer.byteLength; this.totalBytes = this.readOffset; } else { console.log( value.buffer.byteLength, this.readOffset, this.totalBytes ); } if (this.totalBytes >= (384 * 512) / 2 && !this.started) { this.started = true; this.port.postMessage({ start: this.started }); } }, close() { console.log('stopped'); }, }; try { await this.readable.pipeTo(new WritableStream(source)); } catch (e) { console.warn(e); console.log(this.writeOffset, this.totalBytes); this.endOfStream(); } } endOfStream() { this.port.postMessage({ ended: true, currentTime, currentFrame, readOffset: this.readOffset, readIndex: this.readIndex, writeOffset: this.writeOffet, writeIndex: this.writeIndex, totalBytes: this.totalBytes, }); } process(inputs, outputs) { const channels = outputs.flat(); if ( this.writeOffset >= this.totalBytes || this.totalBytes === this.byteSize ) { console.log(this); this.endOfStream(); return false; } const uint8 = new Uint8Array(512); try { for (let i = 0; i < 512; i++, this.writeOffset++) { if (this.writeOffset === this.byteSize) { break; } uint8[i] = this.memory[this.writeOffset]; // ++this.writeOffset; } const uint16 = new Uint16Array(uint8.buffer); // based on int16ToFloat32 function at https://stackoverflow.com/a/35248852 for (let i = 0, j = 0, n = 1; i < uint16.length; i++) { const int = uint16[i]; // If the high bit is on, then it is a negative number, and actually counts backwards. const float = int >= 0x8000 ? -(0x10000 - int) / 0x8000 : int / 0x7fff; // interleave channels[(n = ++n % 2)][!n ? j++ : j - 1] = float; } } catch (e) { console.error(e); } return true; } } // register processor in AudioWorkletGlobalScope function registerProcessor(name, processorCtor) { return `${processorCtor};\nregisterProcessor('${name}', ${processorCtor.name});`; } const worklet = URL.createObjectURL( new Blob( [ registerProcessor( 'audio-worklet-native-file-stream', AudioWorkletNativeFileStream ), ], { type: 'text/javascript' } ) ); const ac = new AudioContext({ latencyHint: 1, sampleRate: 44100, numberOfChannels: 2, }); ac.onstatechange = e => console.log(ac.state); if (ac.state === 'running') { await ac.suspend(); } await ac.audioWorklet.addModule(worklet); const aw = new AudioWorkletNode( ac, 'audio-worklet-native-file-stream', { numberOfInputs: 1, numberOfOutputs: 2, channelCount: 2, processorOptions: { totalBytes: 0, readIndex: 0, writeIndex: 0, readOffset: 0, writeOffset: 0, done: false, ended: false, started: false, }, } ); aw.onprocessorerror = e => { console.error(e); console.trace(); }; // comment MediaStream, MediaStreamTrack creation const msd = new MediaStreamAudioDestinationNode(ac); const { stream } = msd; const [track] = stream.getAudioTracks(); aw.connect(msd); // aw.connect(ac.destination); const recorder = new MediaRecorder(stream); recorder.ondataavailable = e => console.log(URL.createObjectURL(e.data)); aw.port.onmessage = async e => { console.log(e.data); if ( e.data.start && ac.state === 'suspended' ) { await ac.resume(); recorder.start(); } else { if (recorder.state === 'recording') { recorder.stop(); track.stop(); aw.disconnect(); msd.disconnect(); await ac.suspend(); console.log(track); // gc(); } } }; try { start.disabled = true; controller = new AbortController(); signal = controller.signal; const { body: readable } = await fetch( 'http://localhost:8000?start=true', { cache: 'no-store', signal, } ); aw.port.postMessage(readable, [readable]); } catch (e) { console.warn(e); } finally { } }; stop.onclick = e => { controller.abort(); start.disabled = false; }; </script> </body> </html> ``` -- GitHub Notification of comment by guest271314 Please view or discuss this issue at https://github.com/w3c/webrtc-insertable-streams/issues/41#issuecomment-677991483 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Friday, 21 August 2020 01:44:06 UTC