录音 voice record

摘要:
./ffmpeg_Asm。js“);self.importScripts;letprint=()=˃{};self.onmessage=˃{letblob=event.data;letresult=ffmpeg_run;self.postMessage;};关键是调用ffmpeg_runhttps://archive.org/download/ffmpeg_asm/ffmpeg_asm.js转换器18mb非常大。但是它只需要下载一次,所以可以。wavtomp3的步骤3与上面的步骤相同,使用mono。然后,工作程序使用以下//varurl=require(“file loader!

参考 : 

http://air.ghost.io/recording-to-an-audio-file-using-html5-and-js/ (html5 基础)

https://github.com/muaz-khan/RecordRTC

https://github.com/webpack-contrib/worker-loader

https://github.com/webpack-contrib/file-loader

https://github.com/muaz-khan/RecordRTC/issues/31 (wav 太大的解决方案)

https://github.com/muaz-khan/Ffmpeg.js/blob/master/wav-to-ogg.html#L209 ( ftmpeg wav to ogg 压缩方案 )

http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/ (wav to mp3 压缩方案, 超小, 声音也差.., 可以使用 lamejs 比较新)

使用插件 

npm install recordrtc
npm install --save-dev file-loader
npm install --save-dev worker-loader

要使用 file,worker loading 需要在 tsconfig.app.json 加上 "node"
  "compilerOptions": {"types": [
      "node"
    ]
  },
  import * as RecordRTC from 'recordrtc';
 
startRecord() {
  navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
    let recordRTC = RecordRTC(stream, {
      type: 'audio',
      recorderType: RecordRTC.StereoAudioRecorder,
      disableLogs: true 
      //leftChannel: true,
      //numberOfAudioChannels: 1 // or leftChannel:true
    });
    recordRTC.startRecording();
    this.recordRTC = recordRTC;
    this.stream = stream;
  }).catch(() => {
    console.log('user no allow');
  });
}

通过 html5 的 navigator.mediaDevices.getUserMedia 获取用户的 permission, 然后就可以获取到声音了

通过 RecordRTC 来做录制. 如果是要 to mp3 的话, 可以选择单声道 (不过我试过 to mp3 效果声音效果不好, 所以最好用了 .ogg)

 stop() {
    let recordRTC = this.recordRTC;
    recordRTC.stopRecording(() => {    
      // 关闭 html5 navigator.mediaDevices.getUserMedia
      var track = this.stream.getTracks()[0]; // 0 是因为我们只有一个 track, 是可以 track 2 个的, 声音和影像
      track.stop();

      // ff 可以 skip 掉 fileReader, 直接拿 recordRTC.blob new File 也可以, 因为 ff 返回的就是 ogg 了 
      // 下面是针对 chrome 返回的是 wav, 很大, 所以使用 ffmpeg 压缩去 ogg 
      let fileReader = new FileReader();

      fileReader.onload = () => {
        recordRTC.clearRecordedData(); // reader 读出来后就可以释放 recordRTC 了. 

        //压缩是很慢的, 所以要另开一个线程
        var WorkerConstructor = require("worker-loader!./worker2.js"); 
        var worker = new WorkerConstructor();

        worker.onmessage = (e) => {
          var result = e.data[0];
          // edge 不可以跑哦, 只有 chrome and ff ok 
          var blob = new File([result.data], 'whatever.ogg', {
            type: 'audio/ogg'
          });
          
          let formData = new FormData();
          formData.append('uploadFile', blob, 'whatever.ogg');

          // 上传
          this.http.post('/api/uploadFile', formData).subscribe(() => {
            console.log('done');
          });

          // 做成 audio 
          let audio = new Audio();
          audio.controls = true;
          let url = window.URL.createObjectURL(blob);
          
          audio.src = url;
          let recordMp3Container = document.getElementById('recordmp3-container');
          recordMp3Container.appendChild(audio);
          audio.play();

          // 关闭 worker 
          worker.terminate(); 
        };
    
        worker.postMessage(fileReader.result);
      };

      fileReader.readAsArrayBuffer(recordRTC.blob); 
    });
  }

worker2.js 

let url = require("file-loader!./ffmpeg_asm.js");  

self.importScripts(url);

let print = () => { };
self.onmessage = (event) => {
    let blob = event.data;
    let result = ffmpeg_run({
        print: print,
        printErr: print,
        files: [
            {
                data: new Uint8Array(blob),
                name: "whatever.wav"
            }
        ],
        arguments: '-i whatever.wav -c:a vorbis -b:a 4800k -strict experimental output.ogg'.split(' ')
    });
    self.postMessage(result);
};

关键就是调用了 ffmpeg_run

https://archive.org/download/ffmpeg_asm/ffmpeg_asm.js 

这个转换器 18mb 非常大哦. 不过只要下载一次, 所以 ok 啦. 

wav to mp3 

步骤和上面一下, 使用单声道. 

然后 worker 用下面这个 

//var url = require("file-loader!./lame.all.js");
var url = require("file-loader!lamejs/lame.all.js");  

self.importScripts(url);

self.onmessage = function (e) {
    let stream = e.data.stream;
    let streamArray = new Int16Array(stream);
    streamArray = streamArray.slice(50); //去掉一开始的杂音
    let buffer = [];
    let mp3encoder = new lamejs.Mp3Encoder(1, 44100, 128);

    let mp3Data = mp3encoder.encodeBuffer(streamArray);
    buffer.push(mp3Data);
    mp3Data = mp3encoder.flush(); //获取最后一个 part
    buffer.push(mp3Data);
    let blob = new Blob(buffer, { type: 'audio/mp3' });
    var workerResult = {
        stream: blob
    };
    self.postMessage(workerResult);
}

调用 lamejs 去压缩.

最后想说的是... RecordRTC 这个 plugin 是使用原生 MediaRecorder 接口来实现的

MediaRecorder 只有 chrome and firefox 支持.  chrome 输出的格式是 webm, firefox 则是 ogg, RecordRTC 做了些修改输出的是 wav 

以上 3 种格式 ios safari 都不支持, 它只支持 mp3... 伤感...

recordRTC

录音 voice record第1张录音 voice record第2张
import { HttpClient } from '@angular/common/http';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import * as RecordRTC from 'recordrtc';


declare let MediaRecorder: any;

function invokeSaveAsDialog(file, fileName) {
  if (!file) {
    throw 'Blob object is required.';
  }

  if (!file.type) {
    try {
      file.type = 'video/webm';
    } catch (e) { }
  }

  var fileExtension = (file.type || 'video/webm').split('/')[1];

  if (fileName && fileName.indexOf('.') !== -1) {
    var splitted = fileName.split('.');
    fileName = splitted[0];
    fileExtension = splitted[1];
  }

  var fileFullName = (fileName || (Math.round(Math.random() * 9999999999) + 888888888)) + '.' + fileExtension;

  if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {
    return navigator.msSaveOrOpenBlob(file, fileFullName);
  } else if (typeof navigator.msSaveBlob !== 'undefined') {
    return navigator.msSaveBlob(file, fileFullName);
  }

  var hyperlink = document.createElement('a');
  hyperlink.href = URL.createObjectURL(file);
  hyperlink.download = fileFullName;

  (document.body || document.documentElement).appendChild(hyperlink);

  if (typeof hyperlink.click === 'function') {
    hyperlink.click();
  } else {
    hyperlink.target = '_blank';
    hyperlink.dispatchEvent(new MouseEvent('click', {
      view: window,
      bubbles: true,
      cancelable: true
    }));
  }

  URL.revokeObjectURL(hyperlink.href);
}
let mp3 = true;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {

  constructor(
    private http: HttpClient
  ) { }
  title = 'app';

  recordRTC: any;

  stop() {
    let recordRTC = this.recordRTC;
    recordRTC.stopRecording(() => {
      // 关闭 html5 navigator.mediaDevices.getUserMedia
      var track = this.stream.getTracks()[0]; // 0 是因为我们只有一个 track, 是可以 track 2 个的, 声音和影像
      track.stop();

      // ff 可以 skip 掉 fileReader, 直接拿 recordRTC.blob new File 也可以, 因为 ff 返回的就是 ogg 了 
      // 下面是针对 chrome 返回的是 wav, 很大, 所以使用 ffmpeg 压缩去 ogg 
      let fileReader = new FileReader();

      fileReader.onload = () => {
        recordRTC.clearRecordedData(); // reader 读出来后就可以释放 recordRTC 了. 

        if (mp3) {
          //压缩是很慢的, 所以要另开一个线程        
          var WorkerConstructor = require("worker-loader!./worker.js");
          var worker = new WorkerConstructor();
        }
        else {
          //压缩是很慢的, 所以要另开一个线程        
          var WorkerConstructor = require("worker-loader!./worker2.js");
          var worker = new WorkerConstructor();
        }

        worker.onmessage = (e) => {

          if (mp3) {
            console.log(e);
            var result = e.data.stream;        
            invokeSaveAsDialog(result, 'output.mp3');
            // recordRTC.save('dadad');
          }
          else {
            var result = e.data[0];
            // edge 不可以跑哦, 只有 chrome and ff ok 
            var blob = new File([result.data], 'output.ogg', {
              type: 'audio/ogg'
            });

            let formData = new FormData();
            formData.append('uploadFile', blob, 'output.ogg');

            // 上传
            // this.http.post('/api/uploadFile', formData).subscribe(() => {
            //   console.log('done');
            // });

            invokeSaveAsDialog(blob, 'output.ogg');
            // 做成 audio 
            let audio = new Audio();
            audio.controls = true;
            let url = window.URL.createObjectURL(blob);

            audio.src = url;
            let recordMp3Container = document.getElementById('recordmp3-container');
            recordMp3Container.appendChild(audio);
            audio.play();

            // 关闭 worker 
            worker.terminate();
          }
        };

        worker.postMessage(fileReader.result);
      };

      fileReader.readAsArrayBuffer(recordRTC.blob);
    });
  }

  stream: any

  go() {

    navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {

      let obj = {
        type: 'audio',
        recorderType: RecordRTC.StereoAudioRecorder,
        disableLogs: true,
        // numberOfAudioChannels: 1 // or leftChannel:true
      }
      if(mp3) obj['leftChannel'] = true;
 
      let recordRTC = RecordRTC(stream,obj);
      recordRTC.startRecording();
      this.recordRTC = recordRTC;
      this.stream = stream;
    }).catch(() => {
      console.log('user no allow');
    });
  }
}
View Code

mp3

录音 voice record第3张录音 voice record第4张
//var url = require("file-loader!./lame.all.js");
var url = require("file-loader!lamejs/lame.all.js");

self.importScripts(url);

self.onmessage = function (e) {
    let stream = e.data;
    let streamArray = new Int16Array(stream);
    streamArray = streamArray.slice(50); //去掉一开始的杂音
    let buffer = [];
    let mp3encoder = new lamejs.Mp3Encoder(1, 44100, 128);

    let mp3Data = mp3encoder.encodeBuffer(streamArray);
    buffer.push(mp3Data);
    mp3Data = mp3encoder.flush(); //获取最后一个 part
    buffer.push(mp3Data);
    let blob = new Blob(buffer, { type: 'audio/mp3' });
    var workerResult = {
        stream: blob
    };
    self.postMessage(workerResult);
}
View Code

ogg

录音 voice record第5张录音 voice record第6张
let url = require("file-loader!./ffmpeg_asm.js");

self.importScripts(url);

let print = (text) => {
    console.log(text);
 };
self.onmessage = (event) => {
    console.log('worker e ', event);
    console.log('worker e.data ', event.data);
    let blob = event.data;
    let result = ffmpeg_run({
        print: print,
        printErr: print,
        files: [
            {
                data: new Uint8Array(blob),
                name: "whatever.wav"
            }
        ],
        arguments: '-i whatever.wav -c:a vorbis -b:a 4800k -strict experimental output.ogg'.split(' ')
    });
    self.postMessage(result);
};
View Code

.



免责声明:文章转载自《录音 voice record》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇keystone身份认证服务[转载]Shell删除各种注释的脚本下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

5-URL.createObjectURL()的使用方法

官方说明问文档 URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。 URL.createObjectURL(blob)和FileReader.rea...

ffmpeg 使用 gdb 调试相关技巧

本文说明了,在ffmpeg二次开发或调用库的过程,如何借助于ffmpeg源码进行调试。 注:ffmpeg版本是4.0。 1. 编写代码 编写将pcm数据转换为mp2的代码 pcm_to_mp2.c #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #i...

最全的Windows Azure学习教程汇总

Windows Azure 是微软基于云计算的操作系统,能够为开发者提供一个平台,帮助开发可运行在云服务器、数据中心、Web 和 PC 上的应用程序。 Azure 是一种灵活和支持互操作的平台,能够将处于云端的开发者个人能力,同微软全球数据中心网络托管的服务,比如存储、计算和网络基础设施服务,紧密结合起来。帮助开发者在“云端”和“客户端”同时部署应用,使得...

vue下实现WebRTC

1.1 WebRTC简介 WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的实时通信框架,提供了一系列页面可调用API。 参考定义: 谷歌开放实时通信框架 在上一篇博客Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互 中...

Java实现打包下载BLOB字段中的文件

概述 web项目的文件打包下载实现;servlet接收请求,spring工具类访问数据库及简化大字段内容获取,org.apache.tools.zip打包。 必要提醒:当前总结是继Java实现下载BLOB字段中的文件之后的总结,如有不解之处,请参考之。 核心代码 jdk提供了java.util.zip包,用于实现文件打包的功能,但是对中文名的文件没有很好的...

计算视频播放的时间(pts)

http://yejun8500.blog.163.com/blog/static/463360020095298410979/ 在解码视频流的时候对每一个视频帧都会有一个时间戳pts(显示时间戳),得到这个pts的值,并记下最开始的一个pts值(pts_00),以后画面显示的时间就可以用当前播放的帧的时间戳(pts_now -pts_00)/90000获...