最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

web網(wǎng)頁上實(shí)現(xiàn)錄音功能(vue3組件示例)

 更新時(shí)間:2025年06月24日 09:45:26   作者:重生之我在農(nóng)廠搬磚  
在Vue項(xiàng)目或網(wǎng)頁上實(shí)現(xiàn)文字轉(zhuǎn)換成語音播放功能,通常涉及到語音合成技術(shù),這篇文章主要介紹了web網(wǎng)頁上實(shí)現(xiàn)錄音功能(vue3組件示例)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一. 前言

在Web開發(fā)中實(shí)現(xiàn)音頻錄制功能是許多應(yīng)用場景的常見需求。本文將通過一個(gè)完整的Vue 3組件示例,詳細(xì)解析如何利用現(xiàn)代瀏覽器API實(shí)現(xiàn)網(wǎng)頁端的錄音功能。

二. 技術(shù)實(shí)現(xiàn)

1.核心API介紹

MediaRecorder API 是實(shí)現(xiàn)錄音功能的核心,它允許我們直接捕獲來自用戶設(shè)備的媒體流。主要方法:

getUserMedia() 獲取媒體設(shè)備權(quán)限
MediaRecorder() 創(chuàng)建錄音實(shí)例
ondataavailable 接收音頻數(shù)據(jù)
onstop 處理錄音結(jié)束事件

2.模板部分

<template>
  <div class="voice-recorder">
    <!-- 錄音控制 -->
    <button @click="toggleRecording" :class="{ recording: isRecording }">
      {{ isRecording ? "停止錄音" : "開始錄音" }}
    </button>

    <!-- 生成的音頻文件列表 -->
    <div v-if="audioFiles.length > 0" class="audio-list">
      <div v-for="(audio, index) in audioFiles" :key="index">
        <audio controls :src="audio.url"></audio>
      </div>
    </div>
  </div>
</template>

3.核心邏輯實(shí)現(xiàn)

const isRecording = ref(false);
const mediaRecorder = ref(null);
const audioChunks = ref([]);
const audioFiles = ref([]);
// 開始錄音
const startRecording = async (e) => {
  if (isRecording.value) return;
  try {
    audioChunks.value = [];
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    mediaRecorder.value = new MediaRecorder(stream);

    mediaRecorder.value.ondataavailable = (e) => {
      audioChunks.value.push(e.data);
    };
    mediaRecorder.value.onstop = () => {
      const audioBlob = new Blob(audioChunks.value, { type: "audio/webm" });
      const audioURL = URL.createObjectURL(audioBlob);
      audioFiles.value.push({
        name: `recording_${Date.now()}.${getFileExtension(audioBlob.type)}`,
        url: audioURL,
      });
      audioChunks.value = [];
    };
    mediaRecorder.value.start();
    isRecording.value = true;
  } catch (error) {
    console.error("錄音錯(cuò)誤:", error);
  }
};

4. 關(guān)鍵功能點(diǎn)解析

(1) 音頻格式處理

通過MIME類型映射獲取文件擴(kuò)展名:

// 獲取文件擴(kuò)展名
const getFileExtension = (mimeType) => {
  const extensions = {
    "audio/webm": "webm",
    "audio/ogg": "ogg",
    "audio/mp4": "mp4",
    "audio/mpeg": "mp3",
    "audio/wav": "wav",
  };
  return extensions[mimeType] || "webm";
};

(2) 資源管理

組件卸載時(shí)自動釋放資源:

//停止錄音
const stopRecording = () => {
  console.log("停止錄音");
  isRecording.value = false;
  if (mediaRecorder.value) {
    mediaRecorder.value.stop();
    mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());
  }
};
// 清理資源
onUnmounted(() => {
  stopRecording();
});

三. 完整代碼

<template>
  <div class="voice-recorder">
    <!-- 錄音控制 -->
    <button @click="toggleRecording" :class="{ recording: isRecording }">
      {{ isRecording ? "停止錄音" : "開始錄音" }}
    </button>

    <!-- 生成的音頻文件列表 -->
    <div v-if="audioFiles.length > 0" class="audio-list">
      <div v-for="(audio, index) in audioFiles" :key="index">
        <audio controls :src="audio.url"></audio>
      </div>
    </div>
  </div>
</template>

<script setup>
const isRecording = ref(false);
const mediaRecorder = ref(null);
const audioChunks = ref([]);
const audioFiles = ref([]);

// 開始錄音
const startRecording = async (e) => {
  if (isRecording.value) return;
  try {
    audioChunks.value = [];
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    mediaRecorder.value = new MediaRecorder(stream);

    mediaRecorder.value.ondataavailable = (e) => {
      audioChunks.value.push(e.data);
    };
    mediaRecorder.value.onstop = () => {
      const audioBlob = new Blob(audioChunks.value, { type: "audio/webm" });
      const audioURL = URL.createObjectURL(audioBlob);
      audioFiles.value.push({
        name: `recording_${Date.now()}.${getFileExtension(audioBlob.type)}`,
        url: audioURL,
      });
      audioChunks.value = [];
    };
    mediaRecorder.value.start();
    isRecording.value = true;
  } catch (error) {
    console.error("錄音錯(cuò)誤:", error);
  }
};

//停止錄音
const stopRecording = () => {
  console.log("停止錄音");
  isRecording.value = false;
  if (mediaRecorder.value) {
    mediaRecorder.value.stop();
    mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());
  }
};

// 獲取文件擴(kuò)展名
const getFileExtension = (mimeType) => {
  const extensions = {
    "audio/webm": "webm",
    "audio/ogg": "ogg",
    "audio/mp4": "mp4",
    "audio/mpeg": "mp3",
    "audio/wav": "wav",
  };
  return extensions[mimeType] || "webm";
};

// 切換錄音狀態(tài)
const toggleRecording = () => {
  if (!isRecording.value) {
    startRecording();
  } else {
    if (mediaRecorder.value) {
      mediaRecorder.value.stop();
      mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());
    }
  }
  isRecording.value = !isRecording.value;
};

// 清理資源
onUnmounted(() => {
  stopRecording();
});
</script>

<style lang="scss" scoped>
.voice-recorder {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  button {
    padding: 12px 24px;
    background: #42b983;
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.3s;
    &.recording {
      background: #ff4444;
    }
  }

  button:hover {
    background: #3aa876;
  }

  button:disabled {
    background: #ddd;
    cursor: not-allowed;
  }
}

.recording {
  background-color: #ff4444;
  color: white;
}

.audio-list {
  margin-top: 20px;
}
</style>

四. 功能擴(kuò)展建議

添加錄音時(shí)長顯示

實(shí)現(xiàn)音頻波形可視化

總結(jié)

到此這篇關(guān)于web網(wǎng)頁上實(shí)現(xiàn)錄音功能的文章就介紹到這了,更多相關(guān)vue3 web網(wǎng)頁錄音功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉詳細(xì)代碼

    vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉詳細(xì)代碼

    這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉的相關(guān)資料,使用vue.js實(shí)現(xiàn)tab切換很簡單,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • 掌握Qwik.js,輕松應(yīng)對前端SSR渲染問題

    掌握Qwik.js,輕松應(yīng)對前端SSR渲染問題

    掌握Qwik.js,輕松應(yīng)對前端SSR渲染問題!本指南將為你揭示如何使用這款強(qiáng)大的框架,讓你在前端開發(fā)中游刃有余
    2023-12-12
  • vue組件實(shí)例解析

    vue組件實(shí)例解析

    Tag組件其實(shí)是一個(gè)很小的組件,業(yè)務(wù)價(jià)值很低,主要用于Vue新手入門。主要實(shí)現(xiàn)Vue常用的父組件改變子組件的值,view改變model,model的變化反應(yīng)到view上,事件的綁定等功能。下面跟著小編一起來看下吧
    2017-01-01
  • Vue中@click事件的常見修飾符用法總結(jié)

    Vue中@click事件的常見修飾符用法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Vue中@click事件的常見修飾符用法的相關(guān)資料,@click事件修飾符是在Vue組件中用來修改@click事件行為的特殊標(biāo)記,需要的朋友可以參考下
    2023-10-10
  • vue.js指令v-model實(shí)現(xiàn)方法

    vue.js指令v-model實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了vue.js指令v-model實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Vue實(shí)現(xiàn)下拉加載更多

    Vue實(shí)現(xiàn)下拉加載更多

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)下拉加載更多,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Vue配置文件中的proxy配置方式詳解

    Vue配置文件中的proxy配置方式詳解

    今天被vue中proxy配置困擾了一天,記錄一下,下面這篇文章主要給大家介紹了關(guān)于Vue配置文件中的proxy配置方式的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • vue實(shí)現(xiàn)表格分頁功能

    vue實(shí)現(xiàn)表格分頁功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)表格分頁功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • vue中(el-button的五種類型,三種css格式)

    vue中(el-button的五種類型,三種css格式)

    這篇文章主要介紹了vue中(el-button的五種類型,三種css格式)具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • elementUI?el-table二次封裝的詳細(xì)實(shí)例

    elementUI?el-table二次封裝的詳細(xì)實(shí)例

    在項(xiàng)目中會多次使用表格展示數(shù)據(jù),不對這個(gè)table進(jìn)行二次封裝成我們自己想要的,重復(fù)的代碼量的工作會比較大,下面這篇文章主要給大家介紹了關(guān)于elementUI?el-table二次封裝的相關(guān)資料,需要的朋友可以參考下
    2023-03-03

最新評論

盐池县| 浦北县| 盘山县| 武鸣县| 望奎县| 虎林市| 金秀| 中卫市| 洛阳市| 东海县| 辽阳市| 五台县| 崇信县| 崇左市| 迁西县| 同江市| 航空| 吉首市| 平罗县| 日土县| 靖宇县| 仁怀市| 兴安盟| 栖霞市| 广南县| 石楼县| 会昌县| 营山县| 渭源县| 游戏| 铜鼓县| 义马市| 隆昌县| 区。| 兴义市| 耿马| 凯里市| 德州市| 莆田市| 临颍县| 永康市|