김대연

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

198 KB

# docker build . -t umi0410/khuwitch-express
# docker push umi0410/khuwitch-express
FROM node:13
COPY node_modules node_modules
COPY package.json package.json
RUN npm i
COPY . .
ENV PORT 3303
ENTRYPOINT ["npm"]
CMD ["start"]
\ No newline at end of file