오늘 배워 오늘 쓰는 OpenAPI/프로젝트

OpenAPI 활용 - 8시 뉴스 요약 봇 프로젝트

ai-creator 2020. 5. 4. 19:59
반응형

출처 : https://bitcoinist.com/news-summary-july-6-12/

<< 문제 정의 >>

참 바쁜 세상에 살고 있습니다. 정보는 넘쳐나고 시간은 없다는게 문제지요. 모든 것을 다 읽고 보지 않더라도 중요한 내용만 요약해서 정리해주는 봇이 있었으면 참~ 좋겠습니다.

 

<< 목표 >>

손석희 앵커의 뉴스 브리핑을 요약해겠습니다.

2019년 연말을 뜨겁게 달군 슈가맨 양준일씨의 대한 뉴스브리핑을 사용하고자 합니다. 양준일씨의 등장은 정말 충격적이였고, 경이로웠는데요, 뉴스브리핑에서는 어떻게 설명되었을까요?

 

원본

 

요약본

 

어떠세요? 중요한 문장이 잘 요약된 것 같나요?


<< 사전 준비 >>

1) ffmpeg

- 설치 방법 

> windows : ffmpeg 설치 (for windows)

> mac os

$ brew install ffmpeg

 

- 설치 이유 : ETRI OpenAPI의 경우 제약사항이 있습니다.

> 샘플링 레이트 16kHz, mono channel만 지원

> 60초 이하 파일

이렇게 샘플링레이트 및 channel 변경과 60초 이상되는 컨텐츠를 자르기 위해 ffmpeg을 사용합니다.

 

2) youtube 다운로더 

- 설치 방법 : 

> windows : 유튜브 영상 다운로드 (for windows)

> macos

$ brew install youtube-dl

- 정상 동작 확인

$ youtube-dl -o "%(title)s.%(ext)s" nHSYKBpQFwk  

- 설치 이유 : 유투브에 올라온 JTBC 뉴스를 요약하기 위해서 유투브영상을 다운 받을 수 있도록 준비합니다.

 

3) pydub 라이브러리 설치

$ pip install pydub 
$ pip install gensim

4) ETRI OpenAPI 신청 : ai-creator.tistory.com/58

 

참고) youtube 설치 / ffmpeg 설치에 어려움을 느끼는 분들이라면, 아래 파일을 사용하여 step3 부터 수행합니다.

 

output000000000.wav
0.92MB
output000000001.wav
0.91MB
output000000002.wav
0.92MB
output000000003.wav
0.91MB
output000000004.wav
0.91MB
output000000005.wav
0.92MB
output000000006.wav
0.42MB

 

 

<< 구현 순서 >>

step 1 JTBC 뉴스 다운로드
step 2

전처리

- 오디오 추출

- mp3 -> wav로 포맷 변경

- 오디오 파일 자르기 (30초씩)

step 3 ETRI Speech-To-Text API 호출
step 4 Text 요약

 

# 필요한 라이브러리 import

import subprocess
import os
from gensim.summarization.summarizer import summarize

Step 1) JTBC 뉴스 다운로드

url에서 = 이후의 부분을 추출하여 요청합니다.

예) https://www.youtube.com/watch?v=nHSYKBpQFwk

 

youtube_url = "https://www.youtube.com/watch?v=nHSYKBpQFwk"
subprocess.call(["youtube-dl","-o", "%(title)s.%(ext)s", youtube_url.split("=")[-1]])

Step 2) 전처리

다운로드 받은 파일이 여러개라면, 임의로 1개의 파일 선택하여 진행해보겠습니다.

향후, 반복적인 업무를 피하기 위해서 함수를 만드는 등의 리팩토리 작업을 해보면 파이썬을 다루는 능력이 더 향상될 것입니다!! 

 

ETRI OpenAPI 를 호출하기 위해 제약사항에 명시된 포맷으로 변경합니다.

2-1) 오디오 추출

# mp4 파일 중 첫번째 파일만 임의로 선택
filelist = [file for file in os.listdir(".") if file.endswith(".mp4")]
file = filelist[0]

# audio추출
## -y : 이미존재하는 파일의 경우, overwriting할 수 있도록 설정
subprocess.call(["ffmpeg","-y", "-i", file, "output.mp3"])

2-2) mp3 -> wav 파일로 변경하기

# mp3 -> wav로 변경
## -y : 이미존재하는 파일의 경우, overwriting할 수 있도록 설정
## -ar : sampling rate (etri의 경우 16khz지원)
## -ac : 1 (mono)
subprocess.call(["ffmpeg","-y" ,"-i", "output.mp3","-ac", "1", "-ar", "16000", "output.wav"])

2-3) 오디오 파일 자르기 (30초씩)

subprocess.call(["ffmpeg", "-i", \
                 "output.wav", \
                 "-f", "segment", "-segment_time", "30", \
                 "-c", "copy", "output%09d.wav"])

Step 3)  STT API 호출

음성인식(STT) 빨리 시작하기 를 참고하여, 함수로 만들었습니다.

#-*- coding:utf-8 -*-
import urllib3
import json
import base64
import json

openApiURL = "http://aiopen.etri.re.kr:8000/WiseASR/Recognition"
accessKey = "이곳에 인증키를 넣어주세요"

def etri_stt(audioFilePath):
    languageCode = "korean"

    file = open(audioFilePath, "rb")
    audioContents = base64.b64encode(file.read()).decode("utf8")
    file.close()

    requestJson = {
        "access_key": accessKey,
        "argument": {
            "language_code": languageCode,
            "audio": audioContents
        }
    }

    http = urllib3.PoolManager()
    response = http.request(
        "POST",
        openApiURL,
        headers={"Content-Type": "application/json; charset=UTF-8"},
        body=json.dumps(requestJson)
    )

    print("[responseCode] " + str(response.status))
    print("[responBody]")
    print("===== 결과 확인 ====")
    data = json.loads(response.data.decode("utf-8", errors='ignore'))    
    print(data['return_object']['recognized'])
    
    return data['return_object']['recognized']

파일이 여러개로 분리되었으므로, 파일 개수에 맞춰 etri_stt()를 호출하고, 결과를 차곡 차곡 모아둡니다.

filelist = [file for file in os.listdir(".") if file.startswith("output00")]

text_stacked = ""
for file in filelist:
    print(file)
    text = etri_stt(file)
    text_stacked += text
    
print(text_stacked)

[결과 확인]

어색하게 나온 결과도 있지만, 상당부분 깨끗하게 결과가 나왔네요^^

Step 4) Text 요약

4-1) Text 전처리

여기서 문제가 생겼습니다. Text요약을 할 경우, 문장의 기준이 중요한데요, STT의 결과를 보면 문장 분리가 되어 있지 않습니다. 즉, 구두점이 없어서 기계 입장에서는 문장임을 인식할 수 없는 것이죠. 

어떻게 해야 할까요?

다행히 뉴스의 경우 문장의 끝맺음에 공통점이 있습니다.

~습니다. ~입니다. 처럼 말입니다. 그래서 "니다"로 표현되어 있는 부분을 "니다." 으로 표현해보시죠.

## 구두점 삽입
punctuation_text = text_stacked.replace("니다", "니다.") #습니다. 입니다.
punctuation_text

4-2) 요약

print(summarize(punctuation_text, word_count=50))

[결과 확인]

 

<< 참고 >> 

- 이를 이용해서 회의록 요약 프로젝트를 진행할 수 있습니다. 사용하는 데이터만 youtube 영상 -> 회의녹취 파일로 변경되었을 뿐 처리하는 부분들을 똑같겠죠? 다만, ETRI API 경우 구두점을 제공하지 않고, 일반적인 대화의 경우는 뉴스와는 달리 마지막 문장 표현이 명확하지 않습니다. ~했자나요. ~그랬습니다. ~결론내시죠. 등 말이죠.

 

이를 극복하고 싶다면 구글의 STT OpenAPI의 사용을 추천합니다. 베타로 제공되는 기능이기는 하나, "구두점 삽입" 결과가 매우 우수하다고 느끼실겁니다. 

 

- 이를 활용해서 음성 검색 엔진을 만들면 어떨까? 하는 생각이 들었습니다. 이미지검색도 있는 이 세상에 왜 음성검색은 없는 것일까요? 특히 동영상의 경우 내가 원하는 곳을 찾는게 너무 어렵자나요. 음성 검색이 가능하여 원하는 곳으로 빠르게 이동할 수 있었으면 좋겠습니다. 그런데, STT만 된다면 음성 검색 엔진은 쉽게 만들 수 있습니다. 검색 엔진 자체가 text 기반이므로, 음성을 text로만 만들어 놓으면 너무 쉽게 만들 수 있게 됩니다.

 


저작물의 저작권은 작성자에게 있습니다.
공유는 자유롭게 하시되 댓글 남겨주세요~
상업적 용도로는 무단 사용을 금지합니다.
끝까지 읽어주셔서 감사합니다^^

 

반응형