Javascript 如何使用流将MediaRecorder Web API输出保存到磁盘
我正在尝试内部(因此)并希望将输出作为流处理。作为流处理将允许我在保存到磁盘之前处理MediaRecorder输出,例如,我可以对其进行加密。对于我的特定用例,我只关心音频,所以我没有任何视频元素记录 我最基本的用例是使用流将输出保存到磁盘,但我似乎无法完成这项基本任务,因此我将重点讨论如何实现这一点 问题:如何使用流将MediaRecorder Web API输出保存到磁盘。 我可以使用下载“hack”将文件保存到磁盘,并成功地使用打开、转换(加密)、保存新的加密文件和删除未加密的文件。这意味着我最终必须将未加密的数据保存到磁盘。即使在很短的时间内,这感觉像是一种安全上的妥协,我认为在保存之前加密是很容易避免的 在不同的流对象之间有相当多的交叉线,这是一个风险,但我很惊讶我还没有在线找到解决方案-因此我突然提出了堆栈溢出问题 下面是一个突出显示我所有尝试的项目。中的关键代码是record.js,位于save()函数中 最后,我尝试创建一个合适的Javascript 如何使用流将MediaRecorder Web API输出保存到磁盘,javascript,node.js,stream,electron,mediarecorder-api,Javascript,Node.js,Stream,Electron,Mediarecorder Api,我正在尝试内部(因此)并希望将输出作为流处理。作为流处理将允许我在保存到磁盘之前处理MediaRecorder输出,例如,我可以对其进行加密。对于我的特定用例,我只关心音频,所以我没有任何视频元素记录 我最基本的用例是使用流将输出保存到磁盘,但我似乎无法完成这项基本任务,因此我将重点讨论如何实现这一点 问题:如何使用流将MediaRecorder Web API输出保存到磁盘。 我可以使用下载“hack”将文件保存到磁盘,并成功地使用打开、转换(加密)、保存新的加密文件和删除未加密的文件。这意味
readStream
来插入使用const writeStream=fs.createWriteStream(fPath)创建的writeStream
代码>使用readStream.pipe(writeStream)
总之,我尝试了以下方法:
1<代码>Blob
到readStream
我无法将Blob
转换为readStream
,只能将ReadableStream
、ReadableStreamDefaultReader
或Uint8Array
2Blob
到文件(内存中),然后使用fs.createReadStream()
我似乎无法在fs.createReadStream(url)
中使用ObjectURL
,它坚持附加本地路径。
对的回答表明,这是fs.createReadStream()
的限制,使用http.get()
或request()
不适合我的情况,因为我没有尝试访问远程资源
3Blob
到buffer
,然后使用fs.createReadStream()
我无法将Blob
转换为可在fs.createReadStream(buffer)
中使用的buffer
,只能转换为arrayBuffer
或具有null
字节的缓冲区
非常感谢您的帮助
项目: 节点12.13.0、铬80.0.3987.158和电子8.2.0 设置:
- 这四个文件:main.js、package.json、index.html、record.js都是项目文件夹中的单级文件
你好,世界!
你好,世界!
我们正在使用node document.write(process.versions.node),
Chrome文档.write(进程.版本.Chrome),
和Electron document.write(process.versions.Electron)。
记录
记录器状态:非活动
record.js:
console.log(“helloworld from record.js()”);
const remote=require('electron')。remote;
const path=require('path');
常数fs=要求('fs');
const appDir=remote.app.getPath('userData');
var recButton=document.getElementById(“button_rec”);
var recStatusSpan=document.getElementById(“rec_status”);
无功记录仪;
init=异步函数(){
//html页面事件处理程序:
addEventListener(“单击“,()=>{record()}”);
//设置媒体记录器:
var audioStream=await navigator.mediaDevices.getUserMedia({audio:true});
记录器=新的媒体记录器(audioStream,{mimeType:'audio/webm'});
块=[];
recorder.onstart=(事件)=>{
// ...
}
recorder.ondataavailable=(事件)=>{
推送(事件数据);
}
recorder.onstop=异步(事件)=>{
让fileName=`audiofile_${Date.now().toString()}.webm`;
//下载(块,文件名);//好的,我破解了它…
最终,挑战的关键在于:
如何将node.js中的blob
转换为readablestream
总之,我发现有效的步骤是:blob
arrayBuffer
array
buffer
readStream
我需要以下函数将缓冲区转换为流。并且:
其余转换步骤为一行程序,完整保存功能如下:
save = async function (audioToSave, fPath) {
console.log(`Trying to save to: ${fPath}`);
// create the writeStream - this line creates the 0kb file, ready to be written to
const writeStream = fs.createWriteStream(fPath);
console.log(writeStream); // WriteStream {...}
// The incoming data 'audioToSave' is an array containing a single blob of data.
console.log(audioToSave); // [Blob]
// Lets convert the data to a Blob
var audioBlob = new Blob(audioToSave, {
type: "audio/webm"
});
console.log(audioBlob); // Blob {size: 17955, type: "audio/webm"}
// note: audioBlob = audio[0] has same effect
// now we go through the following process: blob > arrayBuffer > array > buffer > readStream:
const arrayBuffer = await audioBlob.arrayBuffer();
console.log(arrayBuffer); // ArrayBuffer(17955) {}
const array = new Uint8Array(arrayBuffer);
console.log(array); // Uint8Array(17955) [26, 69, ... ]
const buffer = Buffer.from(array);
console.log(buffer); // Buffer(17955) [26, 69, ... ]
let readStream = bufferToStream(buffer);
console.log(readStream); // Readable {_readableState: ReadableState, readable: true, ... }
// and now we can pipe:
readStream.pipe(writeStream);
}
最后,我可以在数据和存储之间使用管道并继续使用其他流函数,例如加密。:)
希望这对其他人也有帮助。最终,我不需要创建一个ReadStream
,只需要这样一个缓冲区:让audio=audioToSave[0];
const audioArrayBuffer=wait audio.arrayBuffer();
const audioArray=new Uint8Array(audioArrayBuffer)
…const audioBuffer=Buffer.from(audioArray);
点击:const writeStream=fs.createWriteStream(fPath);
…writeStream.write(audioBuffer);
现在我可以保存了,避免了“黑客”,在保存之前还没有通过加密。。。
const { app, BrowserWindow, ipcMain } = require('electron');
function createWindow () {
// Create the browser window.
let win = new BrowserWindow({
width: 1000,
height: 800,
x:0,
y:0,
title: "Media Recorder Example",
webPreferences: {
nodeIntegration: true,
devTools: true
}
})
win.openDevTools();
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
<br/><br/>
<div>
<button id="button_rec">Record</button>
<p>recorder state: <span id="rec_status">inactive</span></p>
</div>
</body>
<script src="record.js"></script>
</html>
let { Readable } = require('stream') ;
function bufferToStream(buffer) {
let stream = new Readable ();
stream.push(buffer);
stream.push(null);
return stream;
}
save = async function (audioToSave, fPath) {
console.log(`Trying to save to: ${fPath}`);
// create the writeStream - this line creates the 0kb file, ready to be written to
const writeStream = fs.createWriteStream(fPath);
console.log(writeStream); // WriteStream {...}
// The incoming data 'audioToSave' is an array containing a single blob of data.
console.log(audioToSave); // [Blob]
// Lets convert the data to a Blob
var audioBlob = new Blob(audioToSave, {
type: "audio/webm"
});
console.log(audioBlob); // Blob {size: 17955, type: "audio/webm"}
// note: audioBlob = audio[0] has same effect
// now we go through the following process: blob > arrayBuffer > array > buffer > readStream:
const arrayBuffer = await audioBlob.arrayBuffer();
console.log(arrayBuffer); // ArrayBuffer(17955) {}
const array = new Uint8Array(arrayBuffer);
console.log(array); // Uint8Array(17955) [26, 69, ... ]
const buffer = Buffer.from(array);
console.log(buffer); // Buffer(17955) [26, 69, ... ]
let readStream = bufferToStream(buffer);
console.log(readStream); // Readable {_readableState: ReadableState, readable: true, ... }
// and now we can pipe:
readStream.pipe(writeStream);
}