zhuf 1 year ago
parent
commit
bf08cdeacf
8 changed files with 238 additions and 4 deletions
  1. 2 2
      index.html
  2. 1 1
      src/App.vue
  3. BIN
      src/assets/caiji/frame.webp
  4. 47 0
      src/pages/caiji/sy/name.vue
  5. 28 1
      src/pages/caiji/sy/read.vue
  6. 76 0
      src/pages/caiji/sy/record.vue
  7. 83 0
      test.html
  8. 1 0
      vite.config.ts

+ 2 - 2
index.html

@@ -1,5 +1,5 @@
 <!doctype html>
-<html lang="en">
+<html lang="zh-CN">
   <head>
     <meta charset="UTF-8" />
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
@@ -7,7 +7,7 @@
     <title>Ai慕课</title>
   </head>
   <body class="m-0 p-0">
-    <div id="app" class="h-screen w-screen bg-hex-22252f flex flex-col"></div>
+    <div id="app" class="h-screen w-screen bg-hex-22252f flex flex-col text-white overflow-y-scroll"></div>
     <script type="module" src="/src/main.ts"></script>
   </body>
 </html>

+ 1 - 1
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <van-config-provider theme="dark" :theme-vars="{
+  <van-config-provider class="w-full h-full flex flex-col" theme="dark" :theme-vars="{
     'tabbar-background': '#59595928',
     'tabbar-item-active-background': '#59595928',
     'nav-bar-background': '#00000003',

BIN
src/assets/caiji/frame.webp


+ 47 - 0
src/pages/caiji/sy/name.vue

@@ -0,0 +1,47 @@
+<script setup lang='ts'>
+const router = useRouter()
+
+function onClickLeft() {
+  router.back()
+}
+
+const form = reactive({
+  axa_sycj_zdysyid_v2: undefined,
+  axa_name: undefined,
+  axa_mssc: '',
+  axa_sycj_syxb_v2: 'male'
+})
+function onSubmit(values: any) {
+  console.log('submit', values);
+};
+
+</script>
+
+<template>
+  <van-nav-bar title="声音命名" left-arrow @click-left="onClickLeft"></van-nav-bar>
+  <div class="flex-auto py-4 ">
+    <van-form class="h-full flex flex-col" @submit="onSubmit">
+      <van-cell-group inset>
+        <van-field v-model="form.axa_sycj_zdysyid_v2" name="声音id" label="声音id" placeholder="自定义的声音id,英文或拼音"
+          :rules="[{ required: true, message: '' }]" />
+        <van-field v-model="form.axa_name" name="声音名字" label="声音名字" placeholder="声音名字,一般为中文名"
+          :rules="[{ required: true, message: '' }]" />
+        <van-field name="性别" label="性别" :rules="[{ required: true, message: '' }]">
+          <template #input>
+            <van-radio-group v-model="form.axa_sycj_syxb_v2" direction="horizontal">
+              <van-radio name="male">男性</van-radio>
+              <van-radio name="female">女性</van-radio>
+            </van-radio-group>
+          </template>
+        </van-field>
+        <van-field v-model="form.axa_mssc" name="声音描述" label="声音描述" placeholder="声音描述" rows="3" autosize type="textarea"
+          :rules="[{ required: true, message: '' }]" />
+      </van-cell-group>
+      <div class="px-4 mt-20">
+        <van-button block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>

+ 28 - 1
src/pages/caiji/sy/read.vue

@@ -1,12 +1,39 @@
 <script setup lang='ts'>
+import frame from '~/assets/caiji/frame.webp'
+
 const router = useRouter()
 
 function onClickLeft() {
   router.back()
 }
+
+const leftTime = ref(15)
+const timer = ref()
+
+onMounted(() => {
+  timer.value = setInterval(() => {
+    leftTime.value--
+    if (leftTime.value === 0) {
+      clearInterval(timer.value)
+    }
+  }, 1000)
+})
+
+
 </script>
 
 <template>
   <van-nav-bar title="声音采集" left-arrow @click-left="onClickLeft"></van-nav-bar>
-  <div></div>
+  <div class="flex-auto w-full flex flex-col items-center justify-between py-72px px-6 box-border">
+    <div class="w-full flex flex-col items-center mb-12" @click="router.replace({name:'caiji-sy-name'})">
+      <img class="w-108px mt-6px" :src="frame" alt="">
+      <div class="text-xl mt-16px">定制你的专属声音</div>
+      <div class="text-base mt-22px">保持环境安静</div>
+      <div class="text-base">清晰地说出指令</div>
+    </div>
+
+    <van-button v-if="leftTime" type="danger" size="large" block disabled>{{leftTime}}s 我已知悉</van-button>
+    <van-button v-else type="success" size="large" block icon="success" @click="router.replace({name:'caiji-sy-name'})" >我已知悉</van-button>
+
+  </div>
 </template>

+ 76 - 0
src/pages/caiji/sy/record.vue

@@ -0,0 +1,76 @@
+<script setup lang='ts'>
+
+const router = useRouter()
+
+function onClickLeft() {
+  router.back()
+}
+
+function startAudioRecord() {
+  // 检查浏览器是否支持 getUserMedia API
+if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
+  // 请求用户的音频输入
+  navigator.mediaDevices.getUserMedia({ audio: true })
+    .then(function(stream) {
+      // 创建一个 MediaRecorder 实例
+      const mediaRecorder = new MediaRecorder(stream);
+
+      // 创建一个数组来存储音频数据
+      const audioChunks = [];
+
+      // 当有音频数据可用时,将其添加到数组中
+      mediaRecorder.addEventListener("dataavailable", function(event) {
+        audioChunks.push(event.data);
+      });
+
+      // 当录音结束时,将音频数据转换为 Blob 对象
+      mediaRecorder.addEventListener("stop", function() {
+        const audioBlob = new Blob(audioChunks);
+        const audioUrl = URL.createObjectURL(audioBlob);
+        const audio = new Audio(audioUrl);
+        audio.play();
+      });
+
+      // 开始录音
+      mediaRecorder.start();
+
+      // 5秒后停止录音
+      setTimeout(function() {
+        mediaRecorder.stop();
+      }, 5000);
+    })
+    .catch(function(err) {
+      console.log(err);
+    });
+} else {
+  console.log("浏览器不支持相关 API");
+}
+}
+
+
+</script>
+
+<template>
+  <van-nav-bar title="声音采集" left-arrow @click-left="onClickLeft"></van-nav-bar>
+  <div class="flex-auto w-full flex flex-col items-center justify-between py-72px px-6 box-border">
+    <div class="w-full flex flex-col items-center mb-12">
+      <div class="text-xl mt-26px">1 / 15</div>
+      <p class="text-base indent mt-28px">宁愿用aac也不要用mp3,aac从音质上来说是比mp3要有保证,对声纹模型识别的效果也是有效的,即使aac的压缩比和mp3差不多大。不过,条件允许的话,还是用wav最好了,保16KHz16bit音频的wav,对声纹模型识别是最佳。</p>
+    </div>
+
+
+    <div class="flex w-full justify-around text-hex-242731">
+      <div class="p-4 rounded-8 bg-white ">
+        <van-icon name="volume" size="28" />
+      </div>
+      <div class="p-4 rounded-8 bg-white ">
+        <van-icon name="play" size="28" />
+        <van-icon name="pause" size="28" />
+        <van-icon name="stop" size="28" />
+      </div>
+      <div class="p-4 rounded-8 bg-white ">
+        <van-icon name="success" size="28" />
+      </div>
+    </div>
+  </div>
+</template>

+ 83 - 0
test.html

@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Document</title>
+  <style>
+    * {
+      margin: 0;
+      padding: 0;
+    }
+
+    #video {
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
+  </style>
+  <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
+  <script>
+    // VConsole 默认会挂载到 `window.VConsole` 上
+    var vConsole = new window.VConsole();
+  </script>
+</head>
+
+<body>
+  <video id="video" autoplay></video>
+  <button id="saveButton">保存</button>
+
+  <script>
+    const video = document.getElementById('video');
+
+    let mediaRecorder;
+    let recordedBlobs;
+
+    if (navigator.mediaDevices.getUserMedia) {
+      navigator.mediaDevices.getUserMedia({
+        video: {
+          width: { ideal: 1920 },
+          height: { ideal: 1080 }
+        }
+      })
+        .then(function (stream) {
+          video.srcObject = stream;
+          mediaRecorder = new MediaRecorder(stream);
+          console.log('mediaRecorder : ', mediaRecorder.state, mediaRecorder)
+          mediaRecorder.ondataavailable = event => {
+            console.log('event : ', event)
+            if (event.data && event.data.size > 0) {
+              recordedBlobs.push(event.data);
+            }
+          };
+          mediaRecorder.start(1000);
+          console.log('mediaRecorder : ', mediaRecorder.state, mediaRecorder)
+          recordedBlobs = [];
+        })
+        .catch(function (err) {
+          console.log("Something went wrong!", err);
+        });
+    }
+
+    // 在用户点击按钮时保存录制的视频
+    document.querySelector('#saveButton').addEventListener('click', () => {
+      mediaRecorder.stop();
+      console.log('recordedBlobs : ', recordedBlobs)
+      const blob = new Blob(recordedBlobs, { type: 'video/webm' });
+      const url = window.URL.createObjectURL(blob);
+      const a = document.createElement('a');
+      a.style.display = 'none';
+      a.href = url;
+      a.download = 'test.webm';
+      document.body.appendChild(a);
+      a.click();
+      setTimeout(() => {
+        document.body.removeChild(a);
+        window.URL.revokeObjectURL(url);
+      }, 100);
+    });
+  </script>
+</body>
+
+</html>

+ 1 - 0
vite.config.ts

@@ -19,6 +19,7 @@ export default defineConfig({
   },
   server: {
     hmr: { overlay: false }, // 禁用或配置 HMR 连接 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层
+    port: 9901
   },
   plugins: [
     legacyPlugin({