问题描述
我已经成功录制并添加了录制的音频,并将其放置在HTML页面的音频标签中.
I have successfully recorded and added the recorded audio and placed it in the audio tag of my HTML page.
<音频控件=" src ="blob:https://localhost:3000/494f62b9-0513-4d1c-9206-6569083a2661"<</audio>
此外,我已经使用此行从source标签成功获取了blob源url. var source = document.getElementById("Audio").src;
这是我的Blob网址
Also, I have successfully got the blob source url from the source tag using this line.var source = document.getElementById("Audio").src;
and this is my blob url
blob: https://localhost:3000/494f62b9-0513-4d1c-9206-6569083a2661
现在如何将Blob源URL转换为音频文件并将其发送到我的服务器.我已经尝试了很多,帮助您做到这一点,而且我对这个问题还是陌生的.由于我正在使用此记录器api在所有浏览器上运行,因此只有这样一个机会,即获取blob源,然后将其转换为音频文件,然后使用表单数据将音频文件发送到我的服务器.
Now how to convert the blob source url as an audio file and send it to my server. I have tried a lot, help to do this and I am new to this blob. Since I am using this recorder api to work on all browsers I have only this chance by getting the blob source then converting it into an audio file and sending the audio file to my server using form data.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FeedBack URL</title>
<link rel="shortcut icon" href="./favicon.ico">
<meta content="width=device-width" name="viewport">
<meta name="theme-color" content="#00e5d2">
<style>
* {
padding: 0;
margin: 0
}
a {
color: #009387;
text-decoration: none
}
a:visited {
color: #930087
}
body {
margin: 1rem;
font-family: sans-serif
}
main {
max-width: 28rem;
margin: 0 auto;
position: relative
}
#controls {
display: flex;
margin-top: 2rem
}
button {
flex-grow: 1;
height: 2.5rem;
min-width: 2rem;
border: none;
border-radius: .15rem;
background: blue;
margin-left: 2px;
box-shadow: inset 0 -.15rem 0 rgba(0, 0, 0, .2);
cursor: pointer;
display: flex;
justify-content: center;
align-items: center
}
button:focus,
button:hover {
outline: none;
background: blue;
}
button::-moz-focus-inner {
border: 0
}
button:active {
box-shadow: inset 0 1px 0 rgba(0, 0, 0, .2);
line-height: 3rem
}
button:disabled {
pointer-events: none;
background: #d3d3d3
}
button:first-child {
margin-left: 0
}
button svg {
transform: translateY(-.05rem);
fill: #000;
width: 1.4rem
}
button:active svg {
transform: translateY(0)
}
button:disabled svg {
fill: #9a9a9a
}
button text {
fill: #00e5d2
}
button:focus text,
button:hover text {
fill: #00ffe9
}
button:disabled text {
fill: #d3d3d3
}
#formats,
#mode {
margin-top: .5rem;
font-size: 80%
}
#mode {
float: right
}
#support {
display: none;
margin-top: 2rem;
color: red;
font-weight: 700
}
#list {
margin-top: 1.6rem
}
audio {
display: block;
width: 100%;
margin-top: .2rem
}
li {
list-style: none;
margin-bottom: 1rem
}
.popup-position {
display: none;
position: fixed;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.7);
width: 100%;
height: 100%;
/* // The Modal Wrapper */
}
#popup-wrapper {
text-align: left;
}
/* //The Modal Container */
#popup-container {
background-color: #fff;
padding: 20px;
border-radius: 10px;
width: 300px;
margin: 70px auto;
}
#closePopup {
margin-left: 281px;
margin-top: -18px;
}
</style>
</head>
<body>
<a href="javascript:void(0)" onclick="toggle_visibility('contact-popup');">Open Popup</a>
<div class="popup-position" id="contact-popup">
<div class="popup-wrapper">
<div id="popup-container">
<h5>Feedback</h5>
<p id="closePopup"><a href="javascript:void(0)" style="color: red;" title="Close"
onclick="toggle_visibility('contact-popup');">X</a></p>
<main>
<div id="controls">
<button id="record" disabled="" autocomplete="off" title="Record">
<svg viewBox="0 0 100 100" id="recordButton">
<circle cx="50" cy="50" r="46"></circle>
</svg>
</button>
<button id="pause" disabled="" autocomplete="off" title="Pause">
<svg viewBox="0 0 100 100">
<rect x="14" y="10" width="25" height="80"></rect>
<rect x="62" y="10" width="25" height="80"></rect>
</svg>
</button><button id="resume" disabled="" autocomplete="off" title="Resume">
<svg viewBox="0 0 100 100">
<polygon points="10,10 90,50 10,90"></polygon>
</svg>
</button><button id="stop" autocomplete="off" disabled="" title="Stop">
<svg viewBox="0 0 100 100">
<rect x="12" y="12" width="76" height="76"></rect>
</svg>
</button>
</div>
<div id="mode">
Native support,<a href="?polyfill">force polyfill</a>
</div>
<div id="formats"></div>
<div id="support">
Your browser doesn’t support MediaRecorder
So please use chrome or edge or mozilla
</div>
<ul id="list"></ul>
<form enctype="multipart/form-data"></form>
<input id="image-file" type="file" hidden />
<button type="button" id="formSubmit" onclick="sendto();">Submit</button>
</form>
</main>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
(function () {
var a, i, b, d, f, g, l = ["start", "stop", "pause", "resume"],
m = ["audio/webm", "audio/ogg", "audio/wav"],
j = 1024,
k = 1 << 20;
function n(e) {
var r, $ = Math.abs(e);
return $ >= k ? (r = "MB", e /= k) : $ >= j ? (r = "KB", e /= j) : r = "B", e.toFixed(0).replace(
/(?:\.0*|(\.[^0]+)0+)$/, "$1") + " " + r;
}
function e(e) {
i.innerHTML = "", navigator.mediaDevices.getUserMedia({
audio: !0
}).then(function (r) {
a = new MediaRecorder(r), l.forEach(function (e) {
a.addEventListener(e, t.bind(null, e));
}), a.addEventListener("dataavailable", s), "full" === e ? a.start() : a.start(1e3);
}), b.blur(), setTimeout(myFunction, 16000);
}
function o() {
a.stop(), a.stream.getTracks()[0].stop(), g.blur();
}
function p() {
a.pause(), d.blur();
}
function q() {
a.resume(), f.blur();
}
function s(e) {
var r = document.createElement("li"),
$ = document.createElement("strong");
$.innerText = "dataavailable: ", r.appendChild($);
var a = document.createElement("span");
a.innerText = e.data.type + ", " + n(e.data.size), r.appendChild(a), a.setAttribute("id", "span");
var o = document.createElement("audio");
o.controls = !0, o.src = URL.createObjectURL(e.data), o.setAttribute("id", "Audio"), r.appendChild(o), i
.appendChild(r);
}
function t(e) {
var r = document.createElement("li");
r.innerHTML = "<strong>" + e + ": </strong>" + a.state, "start" === e && (r.innerHTML += ", " + a
.mimeType), i.appendChild(r), "recording" === a.state ? (b.disabled = !0,
f.disabled = !0, d.disabled = !1, g.disabled = !1) : "paused" === a.state ? (b
.disabled = !0, f.disabled = !1, d.disabled = !0, g.disabled = !1) : "inactive" === a
.state && (b.disabled = !1, f.disabled = !0, d.disabled = !0, g
.disabled = !0);
}
i = document.getElementById("list"),
b = document.getElementById("record"),
f = document.getElementById("resume"),
d = document.getElementById("pause"),
g = document.getElementById("stop"),
MediaRecorder.notSupported ? (i.style.display = "none",
document.getElementById("controls").style.display = "none",
document.getElementById("formats").style.display = "none",
document.getElementById("mode").style.display = "none",
document.getElementById("support").style.display = "block") : (document.getElementById("formats")
.innerText = "Format: " + m
.filter(function (e) {
return MediaRecorder.isTypeSupported(e);
}).join(", "), b.addEventListener("click", e.bind(null,
"full")), f.addEventListener("click", q), d.addEventListener("click", p),
g.addEventListener("click", o), b.disabled = !1);
})();
function myFunction() {
document.getElementById("stop").click();
}
function toggle_visibility(id) {
var element = document.getElementById(id);
if (element.style.display == 'block')
element.style.display = 'none';
else
element.style.display = 'block';
}
async function sendto() {
var source = document.getElementById("Audio").src;
$.ajax({
type: 'POST',
url: "http://localhost:3000/audioUpload",
data: data,
cache: false,
processData: false,
contentType: false,
success: function(result) {
}
})
</script>
</body>
</html>
我尝试了提取代码
let file = await fetch(source).then(r => r.blob()).then(blobFile => new File([blobFile], fileName, {
type: res[0]
}));
但是它给了我我不知道如何发送和接收原始数据的原始数据.
But it gives me the raw data I don't know how to send and receive the raw data.
推荐答案
首先,您需要一个适当的函数来发送数据.您最初的 fetch
方法很接近,但并不完美.
First you need a proper function to send your data. Your initial fetch
approach was close, but not perfect.
让我们考虑以下功能.它在 file
参数中包含一个 Blob
.此 Blob
将在答案的后面创建.在 sendAudioFile
函数中,创建一个新的 FormData
对象.将 Blob
附加到formData.
Let's consider the function below. It takes in a Blob
in the file
parameter. This Blob
will be created later in the answer. In the sendAudioFile
function create a new FormData
object. Append the Blob
to the the formData.
现在将具有 POST
方法的 formData
发送到您的服务器,并对 formData
使用 body
属性
Now send the formData
with the POST
method to your server and use the body
property for the formData
.
const sendAudioFile = file => {
const formData = new FormData();
formData.append('audio-file', file);
return fetch('http://localhost:3000/audioUpload', {
method: 'POST',
body: formData
});
};
现在要创建文件,您需要捕获记录的流.现在,您直接将录制内容设置为音频元素,但这对您获取录制的数据毫无用处.
Now to create your file you need to capture the recorded stream. Right now you are directly setting the recording to your audio element, but thats no use for you to get the recorded data.
在 getUserMedia
的回调中添加一个空数组,并将其命名为 data
.该数组将捕获所有记录的数据,并使用它创建一个 Blob
.
Add an empty array inside the callback of getUserMedia
and lets call it data
. This array will capture all the recorded data and use it to create a Blob
.
在 dataavailable
事件处理程序中,将 e.data
(已记录的数据)推入 data
数组.
In the dataavailable
event handler, push the e.data
(which is the recorded data) to the data
array.
添加另一个侦听 stop
事件的事件侦听器.每当记录停止并且收集了所有数据时,请在 stop
事件回调中创建一个 Blob
.您可以指定文件的 MIME类型
来说明其格式.
Add another event listener that listens for the stop
event. Whenever the recording has stopped and all data is collected, create a Blob
in the stop
event callback. You can specify what the MIME type
of the file is to tell it's format.
现在,您的 Blob
具有记录的数据,可以将其传递给 sendAudioFile
函数,该函数会将您的 Blob
发送到服务器./p>
Now you have your Blob
with recorded data and can pass that to the sendAudioFile
function which will send your Blob
to the server.
navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
// Collection for recorded data.
let data = [];
// Recorder instance using the stream.
// Also set the stream as the src for the audio element.
const recorder = new MediaRecorder(stream);
audio.srcObject = stream;
recorder.addEventListener('start', e => {
// Empty the collection when starting recording.
data.length = 0;
});
recorder.addEventListener('dataavailable', event => {
// Push recorded data to collection.
data.push(event.data);
});
// Create a Blob when recording has stopped.
recorder.addEventListener('stop', () => {
const blob = new Blob(data, {
'type': 'audio/mp3'
});
sendAudioFile(blob);
});
// Start the recording.
recorder.start();
});
这篇关于如何将Blob URL转换为音频文件并将其保存到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!