territorium-microphone
Version:
Componente de prueba
230 lines (188 loc) • 6.34 kB
JavaScript
import { defineComponent, useCssVars, pushScopeId, popScopeId, openBlock, createBlock, createVNode, withScopeId } from 'vue';
const __default__ = /*#__PURE__*/defineComponent({
name: 'TerritoriumMicrophone',
// vue component name
props: {
width: {
type: [Number, String],
default: "50px"
},
height: {
type: [Number, String],
default: '20px'
},
lineWidth: {
type: [Number, String],
default: '5'
}
},
data() {
return {
canvasCtx: null,
canvas: null,
audioCtx: null,
analyser: null,
dataArray: null,
bufferLength: null,
mediaRecorder: null,
stream: null,
chunks: [],
source: null,
audioURL: null,
audioFormat: "audio/webm"
};
},
methods: {
startRecord() {
this.mediaRecorder.start();
},
stopRecord() {
if (this.mediaRecorder.state == 'recording') {
this.mediaRecorder.stop(); // this.stream.getTracks().forEach(track => track.stop());
// mediaRecorder.requestData();
}
},
draw() {
const WIDTH = this.canvas.width;
const HEIGHT = this.canvas.height;
requestAnimationFrame(this.draw);
this.analyser.getByteTimeDomainData(this.dataArray);
this.canvasCtx.fillStyle = 'rgb(200, 200, 200)';
this.canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
this.canvasCtx.lineWidth = this.lineWidth;
this.canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
this.canvasCtx.beginPath();
let sliceWidth = WIDTH * 1.0 / this.bufferLength;
let x = 0;
for (let i = 0; i < this.bufferLength; i++) {
let v = this.dataArray[i] / 128.0;
let y = v * HEIGHT / 2;
if (i === 0) {
this.canvasCtx.moveTo(x, y);
} else {
this.canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
this.canvasCtx.lineTo(this.canvas.width, this.canvas.height / 2);
this.canvasCtx.stroke();
},
visualize() {
if (!this.audioCtx) {
this.audioCtx = new AudioContext();
}
this.source = this.audioCtx.createMediaStreamSource(this.stream);
this.analyser = this.audioCtx.createAnalyser();
this.analyser.fftSize = 2048;
this.bufferLength = this.analyser.frequencyBinCount;
this.dataArray = new Uint8Array(this.bufferLength);
this.source.connect(this.analyser);
this.draw();
},
readAudioURL(blob) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
});
},
async mediaRecorderOnStop(e) {
console.log('mediaRecorderOnStop send-url-audio this.chunks 1', this.chunks);
const blob = new Blob(this.chunks, {
'type': this.audioFormat
});
this.chunks = []; // this.audioURL = await this.readAudioURL(blob);
// this.$emit('send-url-audio', this.audioURL);
this.$emit('send-url-audio', blob);
console.log('mediaRecorderOnStop send-url-audio', blob);
console.log('mediaRecorderOnStop send-url-audio this.chunks 2', this.chunks);
},
onDataAvailable(e) {
this.chunks.push(e.data);
},
onError(err) {
console.log('The following error occured: ' + err);
},
updateStreamMic(stream) {
this.canvasCtx = this.$refs.canvas.getContext("2d");
this.canvas = this.$refs.canvas;
this.stream = stream;
this.mediaRecorder = new MediaRecorder(this.stream);
this.mediaRecorder.onstop = this.mediaRecorderOnStop;
this.mediaRecorder.ondataavailable = this.onDataAvailable;
this.visualize();
},
getAudio(audioFormat) {
this.audioFormat = audioFormat;
this.stopRecord();
this.startRecord();
}
}
});
const __injectCSSVars__ = () => {
useCssVars(_ctx => ({
"ec09f2b2": _ctx.width,
"c8d25734": _ctx.height
}));
};
const __setup__ = __default__.setup;
__default__.setup = __setup__ ? (props, ctx) => {
__injectCSSVars__();
return __setup__(props, ctx);
} : __injectCSSVars__;
const _withId = /*#__PURE__*/withScopeId("data-v-2bb71b2e");
pushScopeId("data-v-2bb71b2e");
const _hoisted_1 = {
class: "territorium-microphone"
};
const _hoisted_2 = {
class: "visualizer",
ref: "canvas"
};
popScopeId();
const render = /*#__PURE__*/_withId((_ctx, _cache, $props, $setup, $data, $options) => {
return openBlock(), createBlock("div", _hoisted_1, [createVNode("canvas", _hoisted_2, null, 512)]);
});
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "\n.territorium-microphone[data-v-2bb71b2e] {\n display: flex;\n justify-content: center;\n flex-direction: column;\n text-align: center;\n background-color: aquamarine;\n width: 100%;\n}\n.visualizer[data-v-2bb71b2e]{\n width: var(--ec09f2b2);\n height: var(--c8d25734);\n}\n";
styleInject(css_248z);
__default__.render = render;
__default__.__scopeId = "data-v-2bb71b2e";
// Import vue component
// IIFE injects install function into component, allowing component
// to be registered via Vue.use() as well as Vue.component(),
var entry_esm = /*#__PURE__*/(() => {
// Get component instance
const installable = __default__; // Attach install function executed by Vue.use()
installable.install = app => {
app.component('TerritoriumMicrophone', installable);
};
return installable;
})(); // It's possible to expose named exports when writing components that can
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
// export const RollupDemoDirective = directive;
export default entry_esm;