0. 주제

<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>

 

0.1. 사용 기술

  • 사용자의 화면을 캡쳐하여 텍스트를 인식하는 ocr 기술
  • 텍스트를 다중감성분류하는 nlp 기술
  • 음악을 다중감성분류하는 딥러닝 기술 

 

0.2. 기능

  • 메인기능: 실시간 ocr 수행을 기반으로 한 텍스트 분위기에 맞는 배경음악 제공
  • 부가기능: - on/off, - 음악 장르 취향 설정,  -음악의 fade효과, -예민도 등...

 

0.3. 진행

  •  23년 1학기 캡스톤디자인과창업프로젝트 그로스팀
  •  flask-firebase 수단은 실패로 끝나 다른 수단을 택했다

 


 

1. 데이터 관리

1.1 음악 데이터

firebase web 개발, firebase storage sdk를 사용했다

 

 

 

음성 데이터 다중 감성 분류기를 통해 분류하였다.

위 사진은 '슬픔'으로 판단된 감성을 저장한 firebase storage 모습이다.

 

 

중립음악의 경우, 분류기의 결과가 '중립'이다.

위 사진은 '중립'으로 판단된 로파이 장르의 음악을 저장한 firebase storage 모습이다.

 

 

1.2. 음악 메타(meta)데이터 

 

firebase realtime database를 사용하여 메타데이터를 저장했다.

디렉토리를 통해 top-down 방식으로 음악 위치를 찾을 수 있다.

감성음악/기쁨/001 의 value로 001.mp3의 위치를 반환한다.

 

https://romeoh.tistory.com/entry/Firebase-Python-Firebase-Realtime-Database

 

 

 

2. 개발 환경 설정

2.1. flask

 

python으로 개발하기 위해 flask를 사용했다.

 

 

2.2. firebase

 

 

firebase hosting sdk를 사용해 배포했다.

 

https://romeoh.tistory.com/70

 

 

2.3. postman

 

postman을 사용하여 params와 body request에 대한 api 작동을 확인했다.

 

 

 

 

3. api 코드

3.1. setting

flask, firebase 관련 라이브러리를 import 한다.

firebase sdk를 사용하기 위해 initialize 과정을 거친다.

이 값들은 공개해서는 안된다. 

 

코드의 가장 하단에는 위와 같은 모습이다.

app.run을 통해 대기중인 모습이다.

 

 

 

 

3.2. (nlp)딥러닝 모델과 연동 & 감성분석 결과

 

genre, mode, prediction을 바탕으로 firebase realtime db에서

우리가 원하는 음악의 메타데이터를 가져오는 함수이다.

mode에 따라 3가지로 구분하였으며,

mode2의 경우, 감성음악과 중립음악이 교차적으로 등장할 수 있도록 구성하였다.

 

 

3.3. playlist

 

앞 단계에서 얻은 음악 메타데이터를 사용하는 함수이다.

재생할 음악의 위치가 담긴 리스트를 구성함으로써,

재생목록 playlist(json)를 만들 수 있었다.

 

 

3.4. streamming

 

 

재생할 음악 위치가 담긴 jsonfile을 바탕으로 스트리밍하는 함수이다.

audio/mp3타입으로 반환하며, 현재 곡 종료 후 다음 곡을 자동으로 재생한다.

 

 

request value 의미 사용처
genreId 음악 장르(=genre) query를 위한 조건문(if,elif,else) 속 조건
modeId 재생모드(예민도) query를 위한 조건문(if,elif,else) 속 조건

 

 

 


 

1. 가장먼저 root url에 의해, genreId, modeId가 생성된 상태에서, 진행된다.

2.  nlp 모델결과로 감성prediction을 얻는다.

3. get_genre 함수에서 메타데이터를 얻는다.

4. get_playlist 함수에서 플레이리스트를 얻는다.

5. stream_audio 함수에서 음악을 재생한다.


 

 

 

 

4. 제언

저자는 firebase, flask를 이용한 api를 개발하려고 했지만, api 배포에 실패하였다.

원인은 firebase hosting에 있었으며, 독자들에게 fibase를 통한 api배포를 추천하지 않는다.

 

 

https://ppororo.tistory.com/5

두번째로 시도한 것이 nodejs, aws, filezilla, putty, sql을 이용한 api개발이다.

연동해야 할 기술이 많아 더 복잡하지만, 한번 익히면 그 이후에는 쉬운 방법이다.

api 배포시 방화벽에 막혔는데, 저자는 방화벽을 뚫었지만, 이것이 싫다면, 보안 설정을 잘 하는 것이 좋다.

 

 

 

 

 

 

 

 

0. 주제

<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>

 

0.1. 사용 기술

  • 사용자의 화면을 캡쳐하여 텍스트를 인식하는 ocr 기술
  • 텍스트를 다중감성분류하는 nlp 기술
  • 음악을 다중감성분류하는 딥러닝 기술 

 

0.2. 기능

  • 메인기능: 실시간 ocr 수행을 기반으로 한 텍스트 분위기에 맞는 배경음악 제공
  • 부가기능: - on/off, - 음악 장르 취향 설정,  -음악의 fade효과, -예민도 등...

 

0.3. 진행

  •  23년 1학기 캡스톤디자인과창업프로젝트 그로스팀
  •  현재 개발 완료 단계에 있으며, 저자는 '딥러닝-mysql을 연동하는 aws 서버' 을 담당했다. 
  •  postman, putty, filezilla, vscode, mysql, aws, firebase등을 사용했다.

 


 

1. 데이터 관리

1.1 음악 데이터

firebase web 개발, firebase storage sdk를 사용했다

 

 

 

음성 데이터 다중 감성 분류기를 통해 분류하였다.

위 사진은 '슬픔'으로 판단된 감성을 저장한 firebase storage 모습이다.

 

 

중립음악의 경우, 분류기의 결과가 '중립'이다.

위 사진은 '중립'으로 판단된 로파이 장르의 음악을 저장한 firebase storage 모습이다.

 

 

1.2. 음악 메타(meta)데이터 

1.2.1. mysql 연동

https://poiemaweb.com/nodejs-mysql

https://myinfrabox.tistory.com/213

 

위의 사이트를 참고하여 mysql을 연동하였다.

 

 

 

1.2.2. test relation

test relation은 다음과 같은 구조(schema)를 가진다.

type emotion name locate genre
int varchar varchar varchar varchar

 

  • type : 1 감성음악/ 2중립음악 (not null)
  • emotion: sad, happy등과 같은 감성, 중립음악의 경우 '중립'을 가짐 (not null)
  • name : 음악 파일명 (not null)
  • locate: 음악이 위치한 firebase storage 위치 (not null)
  • genre: 음악장르

 

 

2. 개발 환경 설정

2.1. aws ec2

 

aws ec2를 사용하여 api를 배포했다.

무료티어를 사용했으며, ubuntu 개발로 설정했다.

보안 그룹은 다음과 같다. 

nodejs 코드는 3001포트에서 실행되며, ssh는 22포트에서 실행하도록 설정했다.

 

2.2. putty

 

putty ubuntu를 사용했다.

hostname, port number, SSH-auth를 입력해주면 된다.

이때, hostname은 개발 인스턴스의 public ipv4, 

port number은 앞서 언급했던 22,

SSH-auth은 인스턴스 생성시 사용했던 private key를 넣어준다.

 

 

 

 

2.3. filezilla

 

 

filezilla를 통해 코드 파일을 전송했다.

이때 호스트명을 인스턴스의 public ipv4로 설정해야 한다.

 

 

 

2.4. aws, putty, filezilla 연동

https://copycoding.tistory.com/424

위 사이트를 참고했다

 

2.5. postman

 

postman을 사용하여 params와 body request에 대한 api 작동을 확인했다.

 

 

 

 

3. api 코드

3.1. setting

상단

 

require을 통해 필요한 라이브러리를 불러왔다.

express는 app을 위해, child_process는 nlp코드 연동을 위해,

body-parser는 body request를 받기 위해 불러왔다. 

port=3001로, aws 설정 포트와 맞췄다.

 

 

하단

코드의 가장 하단에는 위와 같은 모습이다.

app.listen을 통해 대기중인 모습이다.

api를 app이라는 이름의 module로 저장했다.

 

 

 

3.2. (nlp)딥러닝 모델과 연동 & 감성분석 결과

 

 

datatext를 process.py(nlp모델) 의 input 값으로 줬을때, 그 결과값(print문)을 저장하는 코드이다.

 

이때, getemotion코드는 async function으로 정의해야 한다.

또한 이 전체 코드를 async func를 처리하기 위해 Promise로 묶었다.

 

spawn을 통해 python 컴파일을 실행했고, 'close', 'error'문을 작성하여, 

컴파일 성공과 실패에 대한 핸들링 로직을 만들었다.

 

예측 결과는 prediction에 저장했다.

 

 

3.3. request params, body

 

 

request params, body를 받아와야 한다.

root url에 대한 코드를 작성함으로써, 항상 초기에 실행되도록 만들었다.

 

genreId, modeId는 params이고, datatext는 body이다.

이때 genreId, modeId는 sql query를 위해 사용된다.

datatext는 3.1.의 딥러닝 모델 input으로 사용된다.

 

try catch문을 통해 datatext-딥러닝 모델 연동을 체크했다.

 

request value 의미 사용처
genreId 음악 장르(=genre) sql query 속 attribute
modeId 재생모드(예민도) sql query를 위한 조건문(if,elif,else) 속 조건
datatext OCR 결과 텍스트 nlp 모델의 input

 

 

 

3.4. sql 연동 & 음악 위치 데이터 

 

 

 

my sql와 연동하여, 음악 메타데이터를 반환하는 async func get_path 코드다.

 이 코드를 async func를 처리하기 위해 Promise로 묶었다.

modeId에 따라 세가지 조건문으로 나뉜다.

if modeId=='1'
else if modeId=='3'
else

 

 

 

modeId가 1일때는 감성음악만을 재생해야 한다. 

nlp모델 예측 결과인 prediction에 해당하는 emotion을 가진 row의 locate attribute를 가져와야 한다.

따라서 sql query를 다음과 같이 작성된다.

SELECT locate FROM test WHERE emotion='${prediction}

 

 

modeId가 3일때는 중립음악만을 재생해야 한다.

nlp예측 결과와 상관없이, 음악종류(type)이 2이고, emotion='중립' 을 가진 row의 locate attribute를 가져와야 한다.

또한 이때, 사용자가 설정한 취향 장르인 genre까지 고려해야 한다.

따라서 sql query를 다음과 같이 작성된다.

 SELECT locate FROM test WHERE type='2' AND genre='${genreId}' AND emotion='중립'

 

 

modeId가 2일때는 감성+중립음악을 재생해야 한다.

감성음악은 prediction에 의존하고, 중립음악은 genreId에 의존한다.

두 조건을 or로 묶어서 사용했다.

따라서 sql query를 다음과 같이 작성된다.

SELECT locate FROM test WHERE emotion='${prediction}' or (emotion='중립' and genre='${genreId}'

 

 

 

 

최종적으로 음악 위치인 locate 데이터가 담긴 리스트가 반환된다.

path 리스트는 json 형식으로 변환했다.

 

 

 

 

3.5. 최종코드1 : 음악 위치 반환

 

 

/play url에 해당하는 코드이다.

async function으로 작성했다. 

왜냐하면, 일부 함수가 async func이기 때문이다.


1. 가장먼저 root url에 의해, genreId, modeId, datatext가 생성된 상태에서, 진행된다.

2. getemotion 함수를 통해 nlp 모델결과로 감성prediction을 얻는다.

3. get_path 함수를 통해 sql 결과로 원하는 음악의 위치 데이터를 얻는다.

4. 테이블 형식(row)의 데이터를 형변환한다.

5. finalPath를 json형태로 반환하여 응답한다.


 

 

3.6. 최종코드2 : 감성 반환

 

/emotion url에 해당하는 코드이다.

async function으로 작성했다. 

왜냐하면, 일부 함수가 async func이기 때문이다.


1. 가장먼저 root url에 의해, genreId, modeId, datatext가 생성된 상태에서, 진행된다.

2. getemotion 함수를 통해 nlp 모델결과로 감성prediction을 얻는다.

3. prediction을 json형태로 반환하여 응답한다.


 

 

 

 

4. 제언

저자는 firebase, flask를 이용한 api를 개발하려고 했지만, api 배포에 실패하였다.

원인은 firebase hosting에 있었으며, 독자들에게 fibase를 통한 api배포를 추천하지 않는다.

 

두번째로 시도한 것이 nodejs, aws, filezilla, putty, sql을 이용한 api개발이다.

연동해야 할 기술이 많아 더 복잡하지만, 한번 익히면 그 이후에는 쉬운 방법이다.

api 배포시 방화벽에 막혔는데, 저자는 방화벽을 뚫었지만, 이것이 싫다면, 보안 설정을 잘 하는 것이 좋다.

 

 

 

5. 참고문헌

 

 

 

 

 

0. 주제

<전자책 텍스트 분석을 통해 분위기에 맞는 배경음악을 제공해주는 백그라운드 앱>

 

0.1. 사용할 기술

  •  사용자의 화면을 캡쳐하여 텍스트를 인식하는 ocr 기술
  • 텍스트를 다중감성분류하는 nlp 기술
  • 음악을 다중감성분류하는 딥러닝 기술 

 

0.2. 기능

  • 메인기능: 실시간 ocr 수행을 기반으로 한 텍스트 분위기에 맞는 배경음악 제공
  • 부가기능: - on/off, - 음악 장르 취향 설정, - 음악의 강도조절, -음악의 fade효과 등...

 

0.3. 진행

  •  22년 2학기 캡스톤디자인과창업프로젝트 스타트팀
  •  현재 기술 검증 단계에 있으며, 저자는 '음악을 다중감성분류하는 딥러닝 기술' + '음악의 fade효과' 을 담당했다. 
  •  colab, python, py.torch 등을 사용했다.

 


 

1. 음성데이터 확인 (eda)

1.1 데이터 구하기

http://www2.projects.science.uu.nl/memotion/emotifydata/

 

Dataset of emotional annotations

Description of the annotations The dataset consists of 400 song excerpts (1 minute long) in 4 genres (rock, classical, pop, electronic). The annotations were collected using GEMS scale (Geneva Emotional Music Scales) [1]. Each participant could select max

www2.projects.science.uu.nl

 

위 사이트에서 제공하는 4개의 음악장르(classical, pop, electronic, rock)별 각 100개의 음성 데이터파일을 사용했다.

우리의 타겟인 감성은 9가지로 분류되며(다중감성분류), 데이터 분포도를 확인해본 결과, 아래와 같은 불균형을 보였다.

 

1.2. 데이터 불균형 해결

1.2.1. 유사한 특성끼리 합치기

 

데이터 불균형을 해결하기 위한 첫번째 시도는 유사한 특성끼리 묶는 것이다.

 

  • 기쁨> amazement, joyful_activation
  • 슬픔> sadness, nostalgia
  • 중립> calmness, tenderness
  • 분노> solemnity, power, tension

 

1.2.2. data augmentation

데이터 개수가 부족하기 때문에 undersampling이 아닌, oversampling을 수행해야 한다.

'sadness'에 해당하는 음성데이터에 관해 augmentation을 진행한다. 10개의 데이터만 추가하기로 결정했다.

(이에 대한 근거로는, 125:97=106:82 이기 때문에,...그냥 저자의 생각에 10개가 적당할 것 같았다.)

진행순서는 아래와 같다.

 

 

 

  • 1. audiomentations 모듈을 설치해준다.

 

 

  • 2. sadness에 해당하는 데이터를 불러온다.

(load_audiofiles는 현재 cell보다 뒤에 정의된 함수라서 물결밑줄이 그어졌다)

 

 

  • 3. sad_data 중에서 10개만 random하게 선택한다

 

 

  • 4. augment 파라미터를 정해주고, augmented data를 얻는다.

 

  • 5. 결과

 

2. 음성데이터 가공

2.1. train, validation dataset 

 

음악 장르별 균등하게 학습될 수 있게 하기 위해 다음의 순서에 따라 진행했다.

 

 

  • 1. 음악 장르별 데이터프레임 만들기
  • 2. 1.에서 제작한 데이터프레임을 train_test_split(test_size=0.2, random_state=0) 사용하여 분리
  • 3. train df, validation df끼리 합치기 (pd.concat)

 

 

 

2.2. 음성 데이터 불러오기

음악 데이터를 불러오기 위해, librosa.load를 사용했다.

 파일 경로와 sample_rate를 입력받으면, signal ( type: array) 을 반환하는 함수를 만들었다. 

 

 

2.3. feature, label을 통해, train_data, train_label / val_data, val_label 만들기

 

 

앞서 정의한 load_audiofiles를 바탕으로 멜로디 특성을 담기 위한 함수를 정의했다.

 타켓은 역시나 '감성, feeling, emotion' 이다.

 

tag를 사용하여 train데이터에만 augmeted data를 추가한다.

shape을 확인했을 때, 320+10=330으로 제대로 추가됨을 확인했다.

 

 

2.4. label encoding

target label이 str(문자열)이므로 LabelEncoder를 통해 int(정수)로 변환시킨다.

 

 

2.5. 음성 신호 전처리

 

( https://ahnjg.tistory.com/93 링크를 참고하였다.)

음성 신호를 전처리하기 위해, 성능이 좋아 많은 이들이 사용하는,

fourier transform + mel-filter = melspectrogram 을 사용했다.

사람의 청각기관을 반영했다는 특징역시 선택이유 중 하나이다.

melspectrogram을 통해 음성데이터를 변환해준다.

 

 

 

2.6. 정규화

mel_train, me_val 을 standardscaler로 정규화하고, (개수, 1, height, width)의 크기를 얻었다.

 

 

3. 모델 설계 및 평가

3.0. 모델 설계 

train 데이터 개수가 적기 때문에 과적합 가능성이 크다. 따라서 두가지 방법을 시도했다.

1. dropout

2. 적은 layer 

 

3.1. 합성곱층 4개, 합성곱 끝날때마다 dropout

 

cnn layer (4 layer, convolution) 를 직접 쌓았다. 

음성데이터이기 때문에 층을 너무 작지 않거나 크기않게 4개로 설정했다.

relu 활성화함수를 사용했고, 마지막에는 softmax를 사용했다.

각 합성곱이 끝날때마다 dropout, batchnormalization을 했다.

또한 4개의 다중감성 분류이므로, num_emotions=4로 설정했다. 

 

 

SGD optimizer를 사용했으며, learning rate=0.01, momentum=0.9로 설정했다.

출력속도를 높이기 위해 epochs=10으로 설정했으니, 데이터양과 시간이 충분한 사람은 

epochs=64로 수정하는 것을 권한다.

 

 

loss는 crossentropyloss를 사용했다.

 

accuracy_score을 확인했을 때, 'y_true == y_pred'이라는 문구가 출력되었다. validation data에 관해 정확한 예측을 수행하였음을 확인했다.

loss 그래프를 그려본 결과, epoch가 진행함에도 변화하지 않았다.

즉, 초기에 학습이 모두 완료가 된다는 뜻이므로, 데이터 개수가 너무 적어서 발생한 문제같다...

그래도 혹시 모르니까, 파라미터를 바꿔가면서 결과값을 확인해봤다. (3.2.에서 진행함)

 

 

inverse_transform을 사용하여 label encdoing 역변환하였을때, validiation data 예측은 위와 같은 결과를 보인다. 

 

 

3.2. 합성곱층 4개, 합성곱 끝날때마다 dropout + 파라미터 변화

SGD 대신 ADAM optimizer를 사용했고, learning rate=0.0001로 설정했다.

이외의 파라미터는 동일하다.

 

이번에도 loss가 상수함수의 꼴을 나타냈다. (즉, y_pred==y)

( 예측결과에 차이가 있는 것은 train, test 분리가 다르게 되었기 때문이다. )

 

3.3. 결론

데이터개수 부족으로 인해, 신경망 초기에서 모든 학슴이 완료되는 것으로 확인되었다.

또한, 결과가 너무 좋게 나왔다.

모델 자체는 문제가 없어 보였으므로, 앞으로도 모델1,2 + alpha 를 사용하여 진행할 생각이다.

 

3.4. 데이터 구하기 

https://www.sellbuymusic.com/search/freebgm

https://pixabay.com/music/

 

음악 태그를 바탕으로 label을 붙어서 데이터를 수집중에 있다.

 

 

 

4. 음성 fade in, out 기술

4.1. fade out

 

sample audio data (.wav)를 다운받아서 진행했다.

이 파일은 기차의 휘슬소리로, 크게 2번 경적을 울린다.

 

 

fade out 함수를 만들어준다.

멜로디(주파수), 음압에 대해 각각 fade 효과를 적용해야 한다.

따라서, 입력받은 2차원 데이터를 각각 1차원 데이터로 처리하여(인덱싱) 선형연산을 해준다.

 

 

시간이 지날수록 소리가 작아져야 하기때문에, 점진적으로 작아지는 가중치를 곱해줘야 한다.

이를 위해 np.linspace(1.0,2.0, length)를 사용했다. 

 

 

 

4.3. 그래프 그리기에 정의한 함수를 바탕으로 결과를 출력해본 결과이다.

사진과 같이 fade-out이 잘 이루어진 것을 확인할 수 있다.

 

 

audio를 출력하여 직접 들어본 결과 역시 fade-out이 잘 이뤄짐을 확인할 수 있었다.

 

 

 

 

4.2. fade in

 

4.1. fade out 과 유사하게 진행하되, 연산위치와 가중치만 바꿔주면 된다.

연산위치는 음악의 앞부분, 

가중치는 점진적으로 커쳐야하기 때문에, linspace(0.0,1.0,length)를 사용한다.

 

 

결과는 위와 같이 예쁘게 fade in이 된 것을 확인 할 수 있다.

 

 

4.3. 그래프 그리기 

새롭게 정의한 함수는 위의 두 가지이다.

하나는 waveform(소리의 파동) 출력함수이고, 하나는 specgram(소리의 스펙트럼) 출력함수이다.

 

파형에서는 시간축의 변화에 따른 진폭 축의 변화를 볼 수 있고, 스펙트럼에서는 주파수 축의 변화에 따른 진폭 축의 변화를 볼 수 있는 반면, 스펙트로그램에서는 시간축과 주파수 축의 변화에 따라 진폭의 차이를 인쇄 농도 / 표시 색상의 차이로 나타낸다. (http://ko.wordow.com/english/dictionary/spectrogram)

 

 

 

 

5. 추후계획

  • 감성이 라벨링된 크기가 큰 데이터셋 찾기
  • 모델 성능 개선
  • 사용자 취향에 따른, 음악 장르 설정 및 음악 강도 조절 기술 구현하기

 

 

6. 참고문헌

 

 

 

 

 

+ Recent posts