jichoi / lms_front star
dajeong 2024-08-12
240812 정다정 단어장 스피킹 녹음 기능 추가
@e47769b90c7ad4f0b34f38bb2a56a8a69a894941
client/views/pages/main/Chapter/Chapter2_1.vue
--- client/views/pages/main/Chapter/Chapter2_1.vue
+++ client/views/pages/main/Chapter/Chapter2_1.vue
@@ -1,63 +1,169 @@
 <template>
-    <div id="Chapter1_1" class="content-wrap">
+  <div id="Chapter1_1" class="content-wrap">
       <div class="title-box mb25 flex align-center mt40">
-        <span class="title mr40">1. Hello WORLD</span>
-        <span class="subtitle">my name is dd</span>
+          <span class="title mr40">1. Hello WORLD</span>
+          <span class="subtitle">my name is dd</span>
       </div>
       <div class="flex justify-between align-center">
-        <div class="pre-btn" @click="goToPage('Chapter2')"><img src="../../../../resources/img/left.png" alt=""></div>
-        <div class="content title-box">
-         <p class="title mt25 title-bg">step2</p>
-          <div class="flex align-center mb30">
-          <p class="subtitle2 mr20">오늘 배웠던 단어를 말하고 생성된 예문을 따라 읽어보세요</p>
-          <!-- <button><img src="../../../../resources/img/btn10_s.png" alt="">
-          </button> -->
-        </div>
-          <div class="flex justify-center ">
-          <div class="readGroup">
-             <section >
-                 <div class="imgGroup flex justify-center">
-                    <div class="mic-btn">
-                       <img src="../../../../resources/img/btn11_s.png" alt="">
-                    </div>
-    
-                 </div>
-                <article >
-                  <input type="text" class="speak mb25" placeholder="오늘 배운 단어를 말해보세요!">
-                  <p class="read-ai"><img style="margin-top: -5px;" src="../../../../resources/img/img43_s.png" alt=""></p>
-                </article>
-                
-              </section>
-  
+          <div class="pre-btn" @click="goToPage('Chapter2')">
+              <img src="../../../../resources/img/left.png" alt="" />
           </div>
-        </div>
-        </div>
-        <div class="next-btn" @click="goToPage('Chapter2_2')"><img src="../../../../resources/img/right.png" alt=""></div>
+          <div class="content title-box">
+              <p class="title mt25 title-bg">step2</p>
+              <div class="flex align-center mb30">
+                  <p class="subtitle2 mr20">오늘 배웠던 단어를 말하고 생성된 예문을 따라 읽어보세요</p>
+                  <!-- <button><img src="../../../../resources/img/btn10_s.png" alt="">
+        </button> -->
+              </div>
+              <div>
+                  <img src="http://localhost:8081/client/build/dad67b1726cb2d2b215965b433149ca3.png" data-num="1" />
+                  <p> {{ word }} </p>
+                  <p> {{ mean }} </p>
+                </div>
+              <div class="flex justify-center">
+                  <div class="readGroup">
+                      <section>
+                          <div class="imgGroup flex justify-center">
+                              <!-- 녹음 버튼 -->
+                              <div :class="['mic-btn', { notRecording: !isRecording }]" @click="toggleRecording">
+                                  <img src="../../../../resources/img/btn11_s.png" alt="" />
+                              </div>
+                          </div>
+                          <article>
+                              <p class="speakText mb25">
+                                  <span v-if="transcription === null"
+                                      >위의 버튼을 누른 후 오늘 배운 단어를 말해보세요!</span
+                                  >
+                                  <span v-else-if="!transcription || transcription.trim() === ''"
+                                      >다시 말해보세요!</span
+                                  >
+                                  <span v-else>{{ transcription }}</span>
+                              </p>
+                              <p class="read-ai">
+                                  <img style="margin-top: -5px" src="../../../../resources/img/img43_s.png" alt="" />
+                              </p>
+                          </article>
+                      </section>
+                  </div>
+              </div>
+          </div>
+          <div class="next-btn" @click="goToPage('Chapter2_2')">
+              <img src="../../../../resources/img/right.png" alt="" />
+          </div>
       </div>
-    </div>
-  </template>
-  
-  <script>
-  export default {
-    data() {
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import SvgIcon from '@jamescoyle/vue-icon';
+import { mdiStop } from '@mdi/js';
+export default {
+  data() {
       return {
-      }
-    },
-    methods: {
+          isRecording: false, // 녹음 중 여부
+          mediaRecorder: null,
+          audioChunks: [], // 녹음된 오디오 데이터
+          audioBlob: null, // 오디오 Blob 객체
+          transcription: null, // 서버에서 받아온 텍스트 결과
+          stream: null, // MediaStream 객체
+
+          path: mdiStop,
+
+          /* audioURL : null // 오디오 URL 객체 */
+
+          word : "apple",
+          mean : "사과",
+          imageSrc : "http://localhost:8081/client/build/dad67b1726cb2d2b215965b433149ca3.png"
+      };
+  },
+  methods: {
       goToPage(page) {
-        this.$router.push({ name: page });
-      }
-    },
-    watch: {
-  
-    },
-    computed: {
-  
-    },
-    components: {
-    },
-    mounted() {
-      
-    }
-  }
-  </script>
(No newline at end of file)
+          this.$router.push({ name: page });
+      },
+      // 녹음 시작/중지 토글
+      async toggleRecording() {
+          if (this.isRecording) {
+              console.log('녹음 그만!');
+              this.stopRecording(); // 녹음 중이면 중지
+          } else {
+              console.log('녹음 시작!');
+              await this.startRecording(); // 녹음 중이 아니면 녹음 시작
+          }
+      },
+
+      // 녹음 시작
+      async startRecording() {
+          this.audioChunks = []; // 오디오 초기화
+          this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+          this.mediaRecorder = new MediaRecorder(this.stream);
+          this.mediaRecorder.ondataavailable = (event) => {
+              this.audioChunks.push(event.data); // 녹음 데이터 저장
+          };
+          this.mediaRecorder.onstop = () => {
+              this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
+
+              /******************************/
+              // this.audioURL = URL.createObjectURL(this.audioBlob); // 오디오 URL 생성
+              // console.log('Audio URL:', this.audioURL);
+              /******************************/
+
+              console.log('Recorded Audio Blob:', this.audioBlob); // 콘솔에 Blob 확인
+              this.sendAudioToServer(); // 서버로 오디오 전송
+          };
+          this.mediaRecorder.start(); // 녹음 시작
+          this.isRecording = true; // 녹음 상태 변경
+      },
+
+      // 녹음 중지
+      stopRecording() {
+          this.mediaRecorder.stop(); // 녹음 중단
+
+          if (this.stream) {
+              this.stream.getTracks().forEach((track) => track.stop()); // 스트림의 모든 트랙 중지
+          }
+
+          this.isRecording = false; // 녹음 상태 변경
+      },
+
+      // 오디오 전송
+      async sendAudioToServer() {
+          const formData = new FormData();
+          formData.append('file', this.audioBlob, 'recording.wav');
+          try {
+              const resposne = await axios.post('/api/speechToText.json', formData, {
+                  headers: {
+                      'Content-Type': 'multipart/form-data',
+                  },
+              });
+              this.transcription = resposne.data;
+              console.log(`받은 데이터 : ${this.transcription}`);
+          } catch (error) {
+              console.log('파일 전송 실패 : ', error);
+          }
+      },
+  },
+  watch: {},
+  computed: {},
+  components: {
+      SvgIcon,
+  },
+  mounted() {},
+};
+</script>
+<style scoped>
+.mic-btn {
+  cursor: pointer;
+}
+.mic-btn.notRecording {
+  background-image: none;
+  cursor: pointer;
+}
+.speakText {
+  background-color: #fff8e9;
+  border: 0;
+}
+.speakText span {
+  font-size: 28px;
+}
+</style>
(No newline at end of file)
Add a comment
List