Generate base64 waveform in audio message body

This commit is contained in:
N-Pex 2024-10-25 11:56:27 +02:00
parent 254eb72870
commit 1d33657569
3 changed files with 125 additions and 0 deletions

View file

@ -6,15 +6,22 @@
<div class="play-time">
{{ currentTime }} / {{ totalTime }}
</div>
<div style="position:relative;flex: 1 1 100%">
<v-slider @change="seeked" :disabled="!info.url" color="currentColor" track-color="#cccccc" class="play-progress" :value="info.playPercent" min="0"
max="100" />
<div style="position:absolute;left:18px;right:18px;top:0;bottom:0;height:100%">
<AudioWaveformView :event="event" style="width:100%;height:100%" />
</div>
</div>
</div>
</template>
<script>
import util from "../../plugins/utils";
import AudioWaveformView from "./AudioWaveformView.vue";
export default {
components: { AudioWaveformView },
props: {
event: {
type: Object,

View file

@ -0,0 +1,79 @@
<template>
<canvas ref="waveform">
</canvas>
</template>
<script>
// import util from "../../plugins/utils";
export default {
props: {
event: {
type: Object,
default: function () {
return null;
},
},
},
data() {
return {
};
},
mounted() {
this.drawWaveform(this.event);
},
methods: {
drawWaveform(event) {
const canvas = this.$refs.waveform;
if (canvas) {
const dpr = window.devicePixelRatio || 1;
canvas.width = canvas.offsetWidth * dpr;
canvas.height = (canvas.offsetHeight) * dpr;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
const base64content = event ? event.getContent().formatted_body : undefined;
if (base64content) {
const data = atob(base64content).split('').map(function (c) { return c.charCodeAt(0); });
const drawLineSegment = (ctx, x, y0, data) => {
ctx.lineWidth = 1; // how thick the line is
ctx.strokeStyle = "#000"; // what color our line is
ctx.beginPath();
ctx.moveTo(x, y0 - data);
ctx.lineTo(x, y0 + data);
ctx.stroke();
};
console.log("W", canvas.width, canvas.height, canvas.offsetWidth, canvas.offsetHeight);
const width = canvas.width;
const height = canvas.height;
const samples = data.length;
for (let i = 0; i < width; i++) {
if (i % 4 == 2 || i % 4 == 3) continue;
const iSample = Math.floor(width == 0 ? 0 :(1000 * i) / width);
const sample = iSample < samples ? data[iSample] : 0;
drawLineSegment(ctx, i, height/2, (sample / 255) * height / 2);
}
}
}
}
},
watch: {
event: {
immediate: false,
handler(event) {
this.drawWaveform(event);
}
}
}
};
</script>
<style lang="scss">
@import "@/assets/css/chat.scss";
</style>