如何将Blob URL转换为音频文件并将其保存到服务器 [英] How to convert a blob URL to a audio file and save it to the server

查看:145
本文介绍了如何将Blob URL转换为音频文件并将其保存到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功录制并添加了录制的音频,并将其放置在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转换为音频文件并将其保存到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆