2014-01-25 6 views

답변

4

현재 브라우저 창에서 현재 오디오 녹음을 재생할 수있는 수많은 끔찍한 예제가 있습니다. 이것을위한 유스 케이스가 존재 하는가? 비디오의 나는 ... 하나는 응용 프로그램과 같은 Skype를 구축하고 미리보기 당신이 비디오에 바보 보면 볼 수있는 창,하지만 오디오를 갖고 싶어 이미징 할 수

나는 하나 개의 좋은 포스트하지만 발견 : From microphone to .WAV with: getUserMedia and Web Audio

데이터를 가져 오는 방법을 보여주는 링크 된 기사의 코드 일부를 이식했습니다.

import 'dart:html'; 
import 'dart:async'; 
import 'dart:web_audio'; 

void main() { 
    window.navigator.getUserMedia(video: true, audio: true).then((MediaStream stream) { 
    var context = new AudioContext(); 
    GainNode volume = context.createGain(); 
    MediaStreamAudioSourceNode audioInput = context.createMediaStreamSource(stream); 
    audioInput.connectNode(volume); 

    int bufferSize = 2048; 
    ScriptProcessorNode recorder = context.createJavaScriptNode(bufferSize, 2, 2); 

    recorder.onAudioProcess.listen((AudioProcessingEvent e) { 
    print('recording'); 
    var left = e.inputBuffer.getChannelData(0); 
    var right = e.inputBuffer.getChannelData(1); 
    print(left); 
    // process Data 
    }); 

    volume.connectNode(recorder); 
    recorder.connectNode(context.destination); 


/** 
* [How to get a file or blob from an object URL?](http://stackoverflow.com/questions/11876175) 
* [Convert blob URL to normal URL](http://stackoverflow.com/questions/14952052/convert-blob-url-to-normal-url) 
* Doesn't work as it seems blob urls are not supported in Dart 
*/ 
// String url = Url.createObjectUrlFromStream(stream); 
// var xhr = new HttpRequest(); 
// xhr.responseType = 'blob'; 
// xhr.onLoad.listen((ProgressEvent e) { 
//  print(xhr.response); 
//  var recoveredBlog = xhr.response; 
//  var reader = new FileReader(); 
// 
//  reader.onLoad.listen((e) { 
//  var blobAsDataUrl = reader.result; 
//  reader.readAsDataUrl(blobAsDataUrl); 
//  }); 
// }); 
// xhr.open('GET', url); 
// xhr.send(); 


/** 
* only for testing purposes 
**/ 
// var audio = document.querySelector('audio') as AudioElement; 
// audio.controls = true; 
// audio.src = url; 
    }); 
} 
+1

위의 링크와 솔루션의 일부를 공유해 주셔서 감사합니다. 완벽한 솔루션은 원시 데이터를 처리하고 링크 된 페이지와 유사한 실제 사운드 파일을 생성해야합니다. JS 솔루션을 Dart로 변환하려고합니다. 곧 결과에 대한 업데이트를 게시하겠습니다. –

+1

[This] (https://github.com/nawafnaim/dart_examples/blob/master/save_mic_sound_to_file.dart)는 다트의 JS 솔루션을 다시 작성하는 최선의 시도입니다. 원시 데이터에서 wav 파일을 생성하지만 파일의 시작 부분에 파일을 손상시키는 두 개의 잘못된 라인이 있습니다 (작동하는 wav 파일과 비교하여 알 수있는 한). –

+0

참조한 JS 솔루션을 성공적으로 다시 작성했습니다. 전체 코드에 대한 내 대답을 참조하십시오. 감사. –

1

this JS solution을 가리키는 Günter Zöchbauer에게 감사드립니다. 나는 Dart에서 코드를 다시 작성했고 작동한다.

import 'dart:html'; 
import 'dart:async'; 
import 'dart:web_audio'; 
import 'dart:typed_data'; 

bool recording; 
List leftchannel; 
List rightchannel; 
int recordingLength; 
int sampleRate; 

void main() { 

    leftchannel = []; 
    rightchannel = []; 
    recordingLength = 0; 
    sampleRate = 44100; 
    recording = true; 

    // add stop button 
    ButtonElement stopBtn = new ButtonElement() 
    ..text = 'Stop' 
    ..onClick.listen((_) { 

     // stop recording 
     recording = false; 

     // we flat the left and right channels down 
     var leftBuffer = mergeBuffers (leftchannel, recordingLength); 
     var rightBuffer = mergeBuffers (rightchannel, recordingLength); 
     // we interleave both channels together 
     var interleaved = interleave(leftBuffer, rightBuffer); 

     // we create our wav file 
     var buffer = new Uint8List(44 + interleaved.length * 2); 
     ByteData view = new ByteData.view(buffer); 

     // RIFF chunk descriptor 
     writeUTFBytes(view, 0, 'RIFF'); 
     view.setUint32(4, 44 + interleaved.length * 2, Endianness.LITTLE_ENDIAN); 
     writeUTFBytes(view, 8, 'WAVE'); 

     // FMT sub-chunk 
     writeUTFBytes(view, 12, 'fmt '); 
     view.setUint32(16, 16, Endianness.LITTLE_ENDIAN); 
     view.setUint16(20, 1, Endianness.LITTLE_ENDIAN); 

     // stereo (2 channels) 
     view.setUint16(22, 2, Endianness.LITTLE_ENDIAN); 
     view.setUint32(24, sampleRate, Endianness.LITTLE_ENDIAN); 
     view.setUint32(28, sampleRate * 4, Endianness.LITTLE_ENDIAN); 
     view.setUint16(32, 4, Endianness.LITTLE_ENDIAN); 
     view.setUint16(34, 16, Endianness.LITTLE_ENDIAN); 

     // data sub-chunk 
     writeUTFBytes(view, 36, 'data'); 
     view.setUint32(40, interleaved.length * 2, Endianness.LITTLE_ENDIAN); 

     // write the PCM samples 
     var lng = interleaved.length; 
     var index = 44; 
     var volume = 1; 
     for (var i = 0; i < lng; i++){ 
     view.setInt16(index, (interleaved[i] * (0x7FFF * volume)).truncate(), Endianness.LITTLE_ENDIAN); 
     index += 2; 
     } 

     // our final binary blob 
     var blob = new Blob ([ view ] , 'audio/wav' ); 

     // let's save it locally 
     String url = Url.createObjectUrlFromBlob(blob); 
     AnchorElement link = new AnchorElement() 
     ..href = url 
     ..text = 'download' 
     ..download = 'output.wav'; 
     document.body.append(link); 

    }); 

    document.body.append(stopBtn); 

    window.navigator.getUserMedia(audio: true).then((MediaStream stream) { 
    var context = new AudioContext(); 
    GainNode volume = context.createGain(); 
    MediaStreamAudioSourceNode audioInput = context.createMediaStreamSource(stream); 
    audioInput.connectNode(volume); 

    int bufferSize = 2048; 
    ScriptProcessorNode recorder = context.createJavaScriptNode(bufferSize, 2, 2); 

    recorder.onAudioProcess.listen((AudioProcessingEvent e) { 
     if (!recording) return; 
     print('recording'); 
     var left = e.inputBuffer.getChannelData(0); 
     var right = e.inputBuffer.getChannelData(1); 
     print(left); 

     // process Data 
     leftchannel.add(new Float32List.fromList(left)); 
     rightchannel.add(new Float32List.fromList(right)); 
     recordingLength += bufferSize; 

    }); 

    volume.connectNode(recorder); 
    recorder.connectNode(context.destination); 

    }); 

} 

void writeUTFBytes(ByteData view, offset, String string){ 
    var lng = string.length; 
    for (var i = 0; i < lng; i++){ 
    view.setUint8(offset + i, string.codeUnitAt(i)); 
    } 
} 

Float32List interleave(leftChannel, rightChannel){ 
    var length = leftChannel.length + rightChannel.length; 
    var result = new Float32List(length); 

    var inputIndex = 0; 

    for (var index = 0; index < length;){ 
    result[index++] = leftChannel[inputIndex]; 
    result[index++] = rightChannel[inputIndex]; 
    inputIndex++; 
    } 
    return result; 
} 

List mergeBuffers(channelBuffer, recordingLength){ 
    List result = new List(); 
    var offset = 0; 
    var lng = channelBuffer.length; 
    for (var i = 0; i < lng; i++){ 
    var buffer = channelBuffer[i]; 
    result.addAll(buffer); 
    } 
    return result; 
} 

당신은 github의 here의 코드를 당겨 수 있습니다.