
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div id="Chapter2_2" class="content-wrap">
<div style="margin: 30px 0px 50px">
<router-link to="/MyPlan.page">
<div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div>
</router-link>
</div>
<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>
</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="subtitle2 "></p>
<p class="title mt25 title-bg">단어로 공부하는 영어</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="imgGroup">
<div class="con">
<img :src="currentCon.imgSrc" alt="">
<p class="title3"><em class="yellow">{{ currentCon.titleEm }}</em>{{ currentCon.title }}</p>
<div class="flex align-center justify-center mt10">
<p class="yellow-box-big">{{ currentCon.boxText }}</p>
<span class="subtitle3">{{ currentCon.subtitle }}</span>
</div>
</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 class="flex justify-center">
<div class="btnGroup mt50 flex justify-between">
<button class="popTxt" v-for="(item, index) in items" :key="index" @click="updateContent(index)"
:class="{ active: selectedIndex === index }">
<img :src="item.imgSrc1">
<img :src="item.imgSrc2" v-if="selectedIndex === index" style="display: block;">
</button>
</div>
</div>
</div>
</div>
<div class="next-btn" @click="goToPage('Chapter2_2')"><img src="../../../../resources/img/right.png" alt="">
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import { mdiStop } from '@mdi/js';
export default {
data() {
return {
items: [
{imgSrc1: 'client/resources/img/img53_6_35s.png', imgSrc2: 'client/resources/img/img53_1_35s.png', con: { imgSrc: 'client/resources/img/img54_s.png', titleEm: 'c', title: 'loud', boxText: '명', subtitle: '구름' } },
{imgSrc1: 'client/resources/img/img53_7_35s.png', imgSrc2: 'client/resources/img/img53_2_35s.png', con: { imgSrc: 'client/resources/img/img40_s.png', titleEm: 'a', title: 'pple', boxText: '명', subtitle: '사과' } },
{imgSrc1: 'client/resources/img/img53_8_35s.png', imgSrc2: 'client/resources/img/img53_3_35s.png', con: { imgSrc: 'client/resources/img/31img40_s.png', titleEm: 'l', title: 'og', boxText: '명', subtitle: '통나무' } },
{imgSrc1: 'client/resources/img/img53_9_35s.png', imgSrc2: 'client/resources/img/img53_4_35s.png', con: { imgSrc: 'client/resources/img/img41_s.png', titleEm: 'g', title: 'uitar', boxText: '명', subtitle: '기타' } },
{imgSrc1: 'client/resources/img/img53_10_35s.png', imgSrc2: 'client/resources/img/img53_5_35s.png', con: { imgSrc: 'client/resources/img/img76_41s.png', titleEm: 'w', title: 'ater melon', boxText: '명', subtitle: '수박' } }
],
currentCon: { imgSrc: 'client/resources/img/img54_s.png', titleEm: 'c', title: 'loud', boxText: '명', subtitle: '구름' },
selectedIndex: 0,
timer: "00",
intervalId: null,
isRecording: false, // 녹음 중 여부
mediaRecorder: null,
audioChunks: [], // 녹음된 오디오 데이터
audioBlob: null, // 오디오 Blob 객체
transcription: null, // 서버에서 받아온 텍스트 결과
stream: null, // MediaStream 객체
path: mdiStop,
};
},
methods: {
goToPage(page) {
this.$router.push({ name: page });
},
updateContent(index) {
this.selectedIndex = index;
this.currentCon = this.items[index].con;
this.startTimer();
},
startTimer() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
this.timer = 5;
this.intervalId = setInterval(() => {
if (this.timer > 0) {
this.timer--;
} else {
clearInterval(this.intervalId);
}
}, 1000);
},
// 녹음 시작/중지 토글
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);
}
},
},
beforeDestroy() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
}
</script>
<style scoped>
.popTxt img{
position: absolute;
top: 0;
left: 0;
}
</style>