node.js - 在节点中将midi转换为mp3
问题描述
所以我在使用scribbletune的节点中开发一个应用程序
要创建一个 midi 文件:
const clip = scribble.clip({
notes: cMajor,
pattern: 'xxxxxxx'
});
scribble.midi(clip, 'c-major.mid');
我希望能够在浏览器中播放这个文件。据我所知,无法使用音频标签在浏览器中播放 midi:
<audio controls>
<source src="horse.ogg" type="audio/ogg">
</audio>
所以我想我应该首先将midi文件转换为mp3文件。我一直在网上搜索可以做到这一点但没有找到任何东西的节点包。
这听起来应该是可能的。
关于如何在节点中实现这一点的任何提示?
解决方案
如果您只想在浏览器中播放生成的 MIDI 并首先将文件转换为ogg并使用音频标签播放它不是必需的,MidiConvert和Tone.js (如Scribbletune文档中简要说明的那样)可以完成这项工作。
我已经编写了一个示例:
const http = require("http");
const MidiConvert = require("midiconvert"); // npm install midiconvert
const scribble = require("scribbletune"); // npm install scribbletune
const createMidiForToneJs = (notes, pattern) => {
let clip = scribble.clip({
notes,
pattern
});
let midiData;
// The callback is called synchronously (https://github.com/scribbletune/scribbletune/blob/ebda52d7a2835f28b3ddab15488c22bc1d425e7b/src/midi.js#L37)
scribble.midi(
clip,
null, // setting filename to null will cause this method to return bytes (via the callback)
(err, bytes) => {
// err is always null
midiData = bytes;
}
);
return MidiConvert.parse(midiData);
};
const server = http.createServer((req, res) => {
// Don't mind the naivety of the following URL router
switch (req.url.toLowerCase()) {
case "/":
res.end(indexHTMLContents);
break;
case "/midi.json":
res.statusCode = 200;
res.setHeader("Content-Type", "application/json");
const jsonString = JSON.stringify(createMidiForToneJs("CM", "xxxxxxx"));
res.end(jsonString);
break;
default:
res.statusCode = 404;
res.end();
}
});
server.listen(3000); // Open http://localhost:3000 in browser
// -- The HTML and Javascript for the "/" route. Obviously, don't do this in production!
const jsToBeExecutedInBrowser = () => {
document.querySelector("button").addEventListener(
"click",
async () => {
Tone.Transport.clear();
Tone.Transport.stop();
const synth = new Tone.Synth().toMaster();
const response = await fetch("/midi.json");
const midiJson = await response.json();
const midi = MidiConvert.fromJSON(midiJson);
Tone.Transport.bpm.value = midi.bpm;
Tone.Transport.timeSignature = midi.timeSignature;
midi.tracks.forEach(track => {
new Tone.Part((time, event) => {
synth.triggerAttackRelease(
event.name,
event.duration,
time,
event.velocity
);
}, track.notes).start(midi.startTime);
});
Tone.Transport.start();
},
false
);
};
const indexHTMLContents = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Midi Player</title>
</head>
<body>
<button>Play!</button>
<script src="https://unpkg.com/tone"></script>
<script src="https://unpkg.com/midiconvert"></script>
<script>
(${jsToBeExecutedInBrowser.toString()})();
</script>
</body>
</html>`;
推荐阅读
- performance - Docker运行容器慢
- android - 错误:此应用程序需要用于 AR 的最新版本的 Google Play 服务
- ios - 快速将动态服务器响应转换为模型类
- javascript - 防止跨域 iframe 中的 url 更改
- python - 如何用 Python 编写一个 excel 文件并向列的每一行添加一个意图,然后是相同的字符串?
- r - R Shiny,没有堆栈跟踪和未使用的参数
- python - IndexError:调试 Python 脚本中的列表索引超出范围
- javascript - VueJS:在href中使用变量
- swiftui - SwiftUI 组合函数 -> 任何发布者返回类型
- javascript - 使用选择多个使用谷歌应用程序脚本将多个值发送到谷歌表格