김대연

Merge branch 'queueingmp3' into 'master'

Add: 음성 재생 작업 Queue, Add: Cloud Infra, Dockerize

어제 회의에서 얘기 나눴던 대로 음성이 중복해서 계속 재생되는 것이 아닌 Queueing 방식을 이용해 하나씩 재생할 수 있도록 수정했습니다.

local에서 docker build 하는 방법을 작성했습니다.

EC2 Server에서도 docker-compose up까지는 동작하도록 해놨으니, 마무리 통합 과정만 거치면 될 듯 합니다.

See merge request !16
...@@ -4,10 +4,6 @@ khuwitch는 다국어 번역 지원하며, 이를 음성으로도 들을 수 있 ...@@ -4,10 +4,6 @@ khuwitch는 다국어 번역 지원하며, 이를 음성으로도 들을 수 있
4 4
5 khuwitch를 이용하면 채널 관리자는 자신의 채널의 외국어 채팅을 한국어로 바로 번역해 볼 수 있고, 필요한 경우 이를 음성파일로 변환하여 재생한 뒤 시청자들에게 송출할 수도 있습니다. 5 khuwitch를 이용하면 채널 관리자는 자신의 채널의 외국어 채팅을 한국어로 바로 번역해 볼 수 있고, 필요한 경우 이를 음성파일로 변환하여 재생한 뒤 시청자들에게 송출할 수도 있습니다.
6 6
7 -## 아키텍쳐
8 -
9 -> 추후 추가 예정
10 -
11 ## 사용되는 API 7 ## 사용되는 API
12 8
13 * [Papago 언어 감지 API](https://developers.naver.com/docs/papago/papago-detectlangs-overview.md) 9 * [Papago 언어 감지 API](https://developers.naver.com/docs/papago/papago-detectlangs-overview.md)
...@@ -15,6 +11,11 @@ khuwitch를 이용하면 채널 관리자는 자신의 채널의 외국어 채 ...@@ -15,6 +11,11 @@ khuwitch를 이용하면 채널 관리자는 자신의 채널의 외국어 채
15 * [Twitch Authentication API](https://dev.twitch.tv/docs/authentication) 11 * [Twitch Authentication API](https://dev.twitch.tv/docs/authentication)
16 * [Twitch Chatbot API](https://dev.twitch.tv/docs/irc) 12 * [Twitch Chatbot API](https://dev.twitch.tv/docs/irc)
17 13
14 +
15 +## 아키텍쳐
16 +
17 +![infra.png](infra.png)
18 +
18 ## 사용된 기술 및 동작 방법 19 ## 사용된 기술 및 동작 방법
19 20
20 khuwitch는 크게 아래의 항목들로 동작한다고 볼 수 있습니다. 21 khuwitch는 크게 아래의 항목들로 동작한다고 볼 수 있습니다.
...@@ -31,44 +32,48 @@ khuwitch는 크게 아래의 항목들로 동작한다고 볼 수 있습니다. ...@@ -31,44 +32,48 @@ khuwitch는 크게 아래의 항목들로 동작한다고 볼 수 있습니다.
31 3. 채팅 메시지가 외국어인 경우 Papago의 번역 API를 이용해 내용을 번역한 뒤 채팅으로 번역 내용을 전송하고, socket io를 통해 현재 khuwith 서비스에 접속 중인 사용자에게도 번역 내용을 전송합니다. 32 3. 채팅 메시지가 외국어인 경우 Papago의 번역 API를 이용해 내용을 번역한 뒤 채팅으로 번역 내용을 전송하고, socket io를 통해 현재 khuwith 서비스에 접속 중인 사용자에게도 번역 내용을 전송합니다.
32 4. frontend에서는 수신한 text를 `AWS Polly` 를 이용해 음성 파일로 변환한 뒤, 접속자의 브라우저에서 재생합니다. 33 4. frontend에서는 수신한 text를 `AWS Polly` 를 이용해 음성 파일로 변환한 뒤, 접속자의 브라우저에서 재생합니다.
33 34
34 -## 빌드 및 실행 방법 35 +## 빌드 및 배포 방법
35 36
36 -> 추후 보완 예정 37 +우선은 docker-compose를 이용해 서버에서 실행할 것이기 때문에 이미지 빌드를 위해 docker를 설치해야하고, 서버에는 docker와 docker-compose를 설치해야합니다.
37 38
38 -### local에서 실행하기 39 +### 빌드
39 -
40 -**frontend**
41 40
41 +frontend를 예시로하겠습니다. backend의 경우 `frontend``server`로 변경하면 됩니다.
42 ```bash 42 ```bash
43 -$ PORT=8000 npm start 43 +# docker 설치 후
44 +$ cd frontend
45 +$ docker build . -t umi0410/khuwitch-frontend
46 +$ docker push umi0410/khuwitch-frontend
44 ``` 47 ```
45 48
46 -**backend** 49 +### 배포
50 +
51 +배포는 frontend든 backend든 상관없이 docker-compose로 한 번에 배포합니다. 빌드 때와 마찬가지로 docker를 설치해주시고, 추가적으로 docker-compose를 설치한 뒤 서비스를 구동시킵니다.
47 ```bash 52 ```bash
48 -$ KHUWITCH_PORT=3000 npm start 53 +# 서버 접속 후 docker 설치 후 docker-compose 설치
54 +$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
55 +$ sudo chmod +x /usr/local/bin/docker-compose
56 +$ curl http://khuhub.khu.ac.kr/2016101168/khuwitch/raw/queueingmp3/docker-compose.yml -o /tmp/docker-compose.yml
57 +$ sudo docker-compose pull && sudo docker-compose /tmp/docker-compose.yml up -d # or docker-compose up -d
49 ``` 58 ```
50 59
51 -### docker image 빌드 후 docker-compose로 실행 60 +### 개발을 위해 실행하기
52 -
53 -**frontend 빌드**
54 61
55 -```bash 62 +**frontend**
56 -$ docker build -f Dockerfile-frontend -t khuwitch/frontend
57 -```
58 63
59 -**backend 빌드**
60 ```bash 64 ```bash
61 -$ docker build -f Dockerfile-backend -t khuwitch/backend 65 +$ cd frontend
66 +$ npm install
67 +$ PORT=8000 npm start
62 ``` 68 ```
63 69
64 -**docker-compose로 실행** 70 +**backend**
65 -
66 ```bash 71 ```bash
67 -$ docker-compose -f docker-compose.yml -f docker-compose-dev.yml up 72 +$ cd server
73 +$ npm install
74 +$ npm start
68 ``` 75 ```
69 76
70 -기본적 설정으로 존재하는 `docker-compose.yml` 에 추가적인 내용을 담은 `docker-compose-{{NAME}}.yml` 을 전달함으로써 설정을 Override할 수 있습니다.
71 -
72 ## 사용 방법 77 ## 사용 방법
73 78
74 _로그인 화면 추후 추가.png_ 79 _로그인 화면 추후 추가.png_
......
1 +version: "3.8"
2 +services:
3 + react:
4 + image: umi0410/khuwitch-react
5 + ports:
6 + - "8000:8000"
7 + express:
8 + image: umi0410/khuwitch-express
9 + ports:
10 + - "3303:3303"
11 +
...\ No newline at end of file ...\ No newline at end of file
1 +# docker build . -t umi0410/khuwitch-react
2 +# docker push umi0410/khuwitch-react
3 +FROM node:13
4 +COPY node_modules node_modules
5 +COPY package.json package.json
6 +RUN npm i
7 +COPY . .
8 +ENV PORT 8000
9 +ENTRYPOINT ["npm"]
10 +CMD ["start"]
...\ No newline at end of file ...\ No newline at end of file
...@@ -8,6 +8,9 @@ import { WatchOutlined } from "@material-ui/icons"; ...@@ -8,6 +8,9 @@ import { WatchOutlined } from "@material-ui/icons";
8 import io from 'socket.io-client' 8 import io from 'socket.io-client'
9 import tts from './tts'; 9 import tts from './tts';
10 10
11 +// audioQueue에서 하나씩 뽑아서 재생한다.
12 +tts.enableAudio()
13 +
11 const socket = io.connect("http://localhost:3303") 14 const socket = io.connect("http://localhost:3303")
12 socket.on("connect", event=>{ 15 socket.on("connect", event=>{
13 // 테스트용으로 umi0410에게 입장. 16 // 테스트용으로 umi0410에게 입장.
...@@ -19,7 +22,8 @@ socket.on("connect", event=>{ ...@@ -19,7 +22,8 @@ socket.on("connect", event=>{
19 socket.on('chat message', (name, msg)=>{ 22 socket.on('chat message', (name, msg)=>{
20 console.log(msg) 23 console.log(msg)
21 console.log("got message") 24 console.log("got message")
22 - tts.speak(msg) 25 + //tts를 audio로 변경해 audioQueue에 집어넣는다.
26 + tts.enqueueTTS(msg)
23 }) 27 })
24 28
25 // 해당 채널을 재생하고자할 때 실행시켜주세요. 29 // 해당 채널을 재생하고자할 때 실행시켜주세요.
......
...@@ -7,7 +7,29 @@ const polly = new AWS.Polly({ ...@@ -7,7 +7,29 @@ const polly = new AWS.Polly({
7 region: 'ap-northeast-2', 7 region: 'ap-northeast-2',
8 }); 8 });
9 9
10 -function speak(text){ 10 +const audioQueue = []
11 +// test data
12 +// const audioQueue = ["https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3", "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"]
13 +
14 +const audio = new Audio()
15 +
16 +// queue에서 작업(재생할 내용)을 0.5초마다 폴링하는 방식
17 +function enableAudio(){
18 + setInterval(()=>{
19 + // 앞선 tts 재생이 종료된 경우에만 새 tts를 실행
20 + if( !audio.paused){ return;}
21 +
22 + let audioFile = audioQueue.shift()
23 + // 재생할 게 있으면 재생
24 + if (audioFile){
25 + console.log(audioFile)
26 + audio.setAttribute("src", audioFile)
27 + audio.play()
28 + }
29 + }, 500)
30 +}
31 +
32 +function enqueueTTS(text){
11 let params = { 33 let params = {
12 'Text': text, 34 'Text': text,
13 'OutputFormat': 'mp3', 35 'OutputFormat': 'mp3',
...@@ -19,15 +41,22 @@ function speak(text){ ...@@ -19,15 +41,22 @@ function speak(text){
19 tts.getSynthesizeSpeechUrl(params, function(error, url) { 41 tts.getSynthesizeSpeechUrl(params, function(error, url) {
20 if (error) { 42 if (error) {
21 } else { 43 } else {
22 - setTimeout(()=>{ 44 + audioQueue.push(url)
23 - console.log("실행")
24 - let audio = new Audio(url)
25 - audio.play()
26 - // .then(delete audio);
27 - }, 3000)
28 } 45 }
29 }) 46 })
30 } 47 }
48 +
49 +console.log("테스트용 TTS 데이터를 주입합니다.")
50 +enqueueTTS(`전에 data hazards에서 3가지 data-dependence를 배웠다. mips인 경우에는 in-order이라 True data dependency 문제밖에 안생겼었다
51 +
52 +근데 out-of-order 관점에서는 3개의 명령어가 동시에 fetch되는 경우를 생각해보자.
53 +
54 +만약 1, 3 line 순서 바뀌면 당연히 결과가 이상해진다. 전에 고려하지 못했던 output dependency 와 anti dependency 고려해줘야한다. `)
55 +enqueueTTS("복잡한 브랜치")
56 +enqueueTTS("빵상 아주머니는 말씀하셨다.")
57 +enqueueTTS("니가가라 하와이")
58 +
31 export default { 59 export default {
32 - "speak": speak, 60 + enableAudio,
61 + enqueueTTS,
33 } 62 }
......

198 KB

1 +# docker build . -t umi0410/khuwitch-express
2 +# docker push umi0410/khuwitch-express
3 +FROM node:13
4 +COPY node_modules node_modules
5 +COPY package.json package.json
6 +RUN npm i
7 +COPY . .
8 +ENV PORT 3303
9 +ENTRYPOINT ["npm"]
10 +CMD ["start"]
...\ No newline at end of file ...\ No newline at end of file