Sunday, 9 April 2017

Sound Only in Electron

I'm attempting to record from within an electron app. I'm using electron-vue as a boilerplate and currently trying to utilize recordrtc then loading the data url into an html audio object however when I playback audio no sound plays. I would like to record just sound natively through electron then eventually upload that file to a server, however, no luck.

https://github.com/SimulatedGREG/electron-vue

https://www.npmjs.com/package/recordrtc

<template>
    <div>
        <div v-if="showRecorder" class="full-width">
            <h2>Record</h2>
            <div class="right half-width">
                <button class="button" v-if="!isRecording" type="button" v-on:click="startRecording">Start &#9658;</button>

                <button class="button" v-else-if="isRecording" type="button" v-on:click="stopRecording">Stop &#9632;</button>

                <button class="button" v-else-if="isRecording" type="button" v-on:click="resetRecording">Reset &#128465;</button>
            </div>
            <div class="left half-width">
                <h3>  </h3>
            </div>
        </div>
        <div v-if="showPlayer" class="full-width">
            <div class="extra-padding">
                <h2> Your Recording </h2>
                <p class="padding">
                    <audio v-bind:controls="controls">
                        <source v-bind:src="src" v-bind:type="type">
                    </audio>
                    <button class="reset" type="button" v-on:click="resetRecording">&#128465;</button>
                </p>
            </div>
            <div class="extra-padding">
                <h2> Save your Recording? </h2>
                <p class="padding">
                    <input v-model="fileName" class="fileName" v-bind:disabled="fileDisabled" type="text"
                           placeholder="File Name"/>
                    <input class="save" type="submit" v-bind:disabled="fileDisabled" v-bind:value="saveButton"
                           v-on:click="save"/>
                </p>
                <p class="error">  </p>
            </div>

        </div>
    </div>
</template>

<script>
  import RecordRTC from 'recordrtc'
  export default {
    props: {
      options: {
        default() {
          return {
            type: 'audio',
            mimeType: 'video/webm',
            bufferSize: 0,
            sampleRate: 44100,
            leftChannel: false,
            disableLogs: false,
            autoWriteToDisk: true
          }
        }
      }
    },
    data() {
      return {
        fileName: '',
        timmer: 15,
        isRecording: false,
        showRecorder: true,
        showPlayer: false,
        errorMessage: '',
        fileDisabled: true,
        saveButton: 'Save',
        src: '',
        controls: false,
        type: 'audio/wav'
      }
    },
    watch: {
      fileName: function (val) {
        if (/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(val)) {
          this.errorMessage = 'No Special Char';
          return;
        }
        else {
          this.errorMessage = '';
          this.fileName = val;
        }
      }
    },
    methods: {
    save() {
        var formData = new FormData();
        // append Blob/File object
        formData.append('audio/wav', this._blob, this.fileName + '.wav');
        this.fileDisabled = true;
        this.saveButton = 'Uploading...'
        // POST /someUrl
        this.$http.post('http://requestb.in/15svx181', formData,
          {
            'headers': {
              'X-CSRF-TOKEN': 'TOKEN',
              'Authorization': 'Bearer TOKEN',
              'Access-Control-Allow-Origin': '*'
            }

          }).then(response => {
          // success callback
          this.resetRecording();
        }, err => {
          // error callback
          this.fileDisabled = false;
          this.saveButton = 'Retry'
        });
      },
      _addStreamStopListener(stream, callback) {
        var streamEndedEvent = 'ended';
        if ('oninactive' in stream) {
          streamEndedEvent = 'inactive'
        }
        this._stream.addEventListener(streamEndedEvent, function () {
          callback();
          callback = function () {
          }
        }, false);
        this._stream.getAudioTracks().forEach(function (track) {
          track.addEventListener(streamEndedEvent, function () {
            callback();
            callback = function () {
            }
          }, false)
        })
      },
      timmerStart(){
        if (this.isRecording === false) return;
        this.timmer -= 1;
        if (this.timmer > -1) {
          var that = this;
          setTimeout(function () {
            that.timmerStart()
          }, 1000);
        }
        else {
          this.stopRecording();
        }
      },
      // CORE
      startRecording() {
        navigator.webkitGetUserMedia(
          {audio: true},
          (audioStream) => {
            this.$emit('record:start');
            this.isRecording = true;
            this.timmerStart();
            this._stream = audioStream;
            this._recordRTC = RecordRTC(audioStream, this.options);
            this._recordRTC.startRecording();
            this._addStreamStopListener(audioStream, () => {
              this.isRecording = false
            })
          },
          (error) => {
            this.$emit('record:error');
            this.isRecording = false
          })
      },
      resetRecording() {
        if (this._recordRTC) {
          this._recordRTC.stopRecording((url) => {
            this._stream.stop();
            this.$emit('record:reset', url)
          })
        }

        this.timmer = 15;
        this.isRecording = false;
        this.showPlayer = false;
        this._recordRTC = null;
        this.showRecorder = true;

      },
      stopRecording() {
        this._recordRTC.stopRecording((url) => {
          this._stream.stop();
          this.$emit('record:success', url);
          this._blob = new Blob([url], {type: 'audio/wav'});
          this.playbackAudio(url);
        });
        this._recordRTC = null
      },
      playbackAudio(url) {
        this.showPlayer = true;
        this.showRecorder = false;
        this.saveButton = 'Save';
        this.fileDisabled = false;
        this.src = url;
        this.controls = true;
      }
    },
    destroyed() {
      this.stopRecording()
    }
  }
</script>


<style>
    input {
        padding: 12px 5px;
        font-size: 17px;
    }

    .save {
        border: 0;
        margin: 0;
        border-radius: 4px;
        padding: 14px 32px;
        cursor: pointer;
        height: 50px;
        display: inline-block;
        font-size: 17px;
        font-weight: 700;
        background-color: #42c299;
        color: #fff;
        position: relative;
    }

    .reset {
        border: 0;
        margin: 0;
        border-radius: 4px;
        padding: 10px;
        cursor: pointer;
        height: 30px;
        display: inline-block;
        font-size: 17px;
        background: none;
        color: #fff;
        position: relative;
        top: -8px;
    }

    .button {
        padding: 5px 10px;
        -webkit-border-radius: 5px;

        -webkit-box-shadow: 0px 3px rgba(128, 128, 128, 1), /* gradient effects */ 0px 4px rgba(118, 118, 118, 1),
        0px 5px rgba(108, 108, 108, 1),
        0px 6px rgba(98, 98, 98, 1),
        0px 7px rgba(88, 88, 88, 1),
        0px 8px rgba(78, 78, 78, 1),
        0px 14px 6px -1px rgba(128, 128, 128, 1); /* shadow */

        -webkit-transition: -webkit-box-shadow .1s ease-in-out;
    }

    .left {
        float: left;
        display: inline-block;
    }

    .right {
        float: right;
        display: inline-block;
    }

    .full-width {
        width: 100%;
    }

    .half-width {
        width: 50%;
    }

    .extra-padding {
        padding: 50px 0 0 0;
    }

    .padding {
        padding: 20px 0 0 0;
    }

    .error {
        color: red;
    }
</style>



via Hickies

No comments:

Post a Comment