Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { Injectable, EventEmitter } from '@angular/core';
- import * as RecordRTC from 'recordrtc';
- import * as Lamejs from 'lamejs';
- navigator.getUserMedia =
- navigator['mediaDevices'] && navigator['mediaDevices'].getUserMedia ?
- navigator['mediaDevices'].getUserMedia : ( navigator['getUserMedia'] || navigator['webkitGetUserMedia'] || navigator['mozGetUserMedia'] || navigator['msGetUserMedia'] );
- enum Time {
- Segundo = 1000,
- Minuto = 60 * Time.Segundo,
- Hora = 60 * Time.Minuto
- }
- @Injectable()
- export class Audio2RecordService {
- private currentAudioStream: MediaStream = null;;
- private recordRTC: any = null;
- private recStoppedEvent: EventEmitter<any> = new EventEmitter<string>();
- private microphone: any = null;
- private audioContext: any = null;
- private mp3encoder;
- private mp3Data = [];
- private lameOptions = {
- channels: 1, //1 for mono or 2 for stereo
- sampleRate: 44100, //44.1khz (normal mp3 samplerate)
- kbps: 128 //encode 128kbps mp3
- };
- // Processor buffer size
- private readonly BUFFER_SIZE = [256, 512, 1024, 2048, 4096, 8192, 16384];
- // MP3 bit ratenumberOfAudioChannels: 1
- private readonly BIT_RATE = [64, 80, 96, 112, 128, 160, 192, 224, 256, 320];
- constructor() {
- this.mp3encoder = new Lamejs.Mp3Encoder(this.lameOptions.channels, this.lameOptions.sampleRate, this.lameOptions.kbps);
- }
- /**
- * Inicia el proceso de grabación.
- *
- * @param maxRecDuration Tiempo maximo de grabación
- */
- startRecording( maxRecDuration?: number ): Promise<void> {
- this.mp3Data = [];
- return new Promise(
- ( resolve, reject ) => {
- this.initMicrophone()
- .then(
- audioStream => {
- this.currentAudioStream = audioStream;
- let options = {
- recorderType: RecordRTC.StereoAudioRecorder,
- type: 'audio',
- mimeType: 'audio/wav',
- numberOfAudioChannels: 1,
- bufferSize: this.BUFFER_SIZE[4],
- bitsPerSecond: this.BIT_RATE[4],
- sampleRate: 44100,
- timeSlice: 1 * Time.Segundo,
- ondataavailable: this.processAudioSlice.bind(this)
- };
- this.recordRTC = RecordRTC(audioStream, options);
- // Auto stop recording after maxRecDuration seconds
- if ( maxRecDuration )
- this.recordRTC.setRecordingDuration(maxRecDuration).onRecordingStopped(this.emitRecStoppedEvent.bind(this));
- this.recordRTC.startRecording();
- resolve();
- }, error => {
- reject(error);
- }
- );
- }
- );
- }
- /**
- * Para la grabación.
- */
- stopRecording(): Promise<Blob> {
- return new Promise(
- (resolve, reject) => {
- this.recordRTC.stopRecording(
- recURL => {
- this.stopRecordingProcess(false);
- let mp3Blob = this.getMP3File()
- resolve(mp3Blob);
- }
- );
- }
- );
- }
- /**
- * Emite una señal indicando que ha alcanzado el tiempo maximo de grabación.
- *
- * @param recURL
- */
- emitRecStoppedEvent(recURL: string){
- this.recStoppedEvent.emit(recURL);
- }
- /**
- * Cancela la grabación.
- */
- cancelRecording() {
- this.recordRTC.stopRecording(
- recURL => this.stopRecordingProcess(false)
- );
- }
- /**
- * Inicia el proceso de paro de la grabación.
- */
- stopRecordingProcess(finish) {
- this.microphone.disconnect();
- this.recordRTC.clearRecordedData();
- this.recordRTC = null;
- if (!finish && this.microphone)
- this.endMicrophone();
- }
- /**
- * Finaliza el microfono.
- */
- endMicrophone() {
- this.currentAudioStream.getAudioTracks().forEach( track => track.stop() );
- this.currentAudioStream = null;
- this.microphone = null;
- this.audioContext.close();
- this.audioContext = null;
- }
- /**
- * Codifica un archivo binario a mp3
- *
- * @param chunkBlob Pedazo de archivo binario a codificar
- */
- processAudioSlice(chunkBlob: Blob) {
- this.convBlobToBufferArray(chunkBlob)
- .then(
- arrayBuffer => this.encodeBufferChunkToMP3(arrayBuffer)
- );
- }
- /**
- * Codifica un pedazo de grabación a MP3.
- *
- * @param audioData Información a codificar
- */
- encodeBufferChunkToMP3(audioData: ArrayBuffer) {
- let samples = new Int16Array(audioData);
- let remaining = samples.length;
- let sampleBlockSize = 1152;
- for (let i = 0; i < samples.length; i += sampleBlockSize) {
- let sampleChunk = samples.subarray(i, i + sampleBlockSize);
- var mp3buf = this.mp3encoder.encodeBuffer(sampleChunk);
- if (mp3buf.length > 0) {
- this.mp3Data.push(new Int8Array(mp3buf));
- }
- }
- }
- /**
- * Obtiene un archivo MP3
- */
- getMP3File(): Blob {
- let mp3buf = this.mp3encoder.flush(); //finish writing mp3
- if (mp3buf.length > 0)
- this.mp3Data.push(new Int8Array(mp3buf));
- let mp3Blob = new Blob(this.mp3Data, {type: 'audio/mp3'});
- window.open(window.URL.createObjectURL(mp3Blob));
- return mp3Blob;
- }
- /**
- * Convierte un objeto Blob a ArrayBuffer
- *
- * @param blob Información binaria
- */
- convBlobToBufferArray(blob: Blob): Promise<ArrayBuffer> {
- return new Promise(
- ( resolve, reject ) => {
- var fileReader = new FileReader();
- fileReader.onload = ( event: any ) => {
- let arrayBuffer = event.target.result;
- resolve(arrayBuffer);
- };
- fileReader.readAsArrayBuffer(blob);
- }
- )
- }
- /**
- * Inicializa el microfono.
- */
- initMicrophone(): Promise<any> {
- return new Promise(
- (resolve, reject) => {
- if (this.microphone == null) {
- var AudioContext = window['AudioContext'] || window['webkitAudioContext'];
- this.audioContext = new AudioContext();
- if (this.audioContext.createScriptProcessor == null)
- this.audioContext.createScriptProcessor = this.audioContext['createJavaScriptNode'];
- if (navigator['mediaDevices'] && navigator['mediaDevices'].getUserMedia) {
- navigator.getUserMedia.call(navigator['mediaDevices'], { audio: true })
- .then(
- stream => {
- this.microphone = this.audioContext.createMediaStreamSource(stream);
- resolve(stream);
- }
- ).catch(
- error => {
- console.error("Error: No se puede iniciar el microfono");
- reject(error);
- }
- );
- } else {
- navigator.getUserMedia(
- { audio: true },
- stream => {
- this.microphone = this.audioContext.createMediaStreamSource(stream);
- resolve(stream);
- },
- error => {
- console.error("Error: No se puede iniciar el microfono");
- reject(error);
- }
- );
- }
- }
- }
- );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement