1 유튜브 → MP4

VideoLAN을 다운로드 받아 사용한다. VLC는 DVD, 오디오 CD, VCD 와 다양한 스트리밍 프로토콜뿐 아니라 대부분의 멀티미디어 파일을 재생할 수 있는 무료 오픈 소스 크로스 플랫폼 멀티미디어 재생기이자 프레임워크다.

실시간 유튜브 동영상을 MP4 형태로 변환시킬 경우 다음 단계를 거쳐 youtube.luac 파일을 처음 업데이트시켜야 한다. 자세한 사항은 Download/Convert YouTube Videos to Mp4 using VLC Media Player [Error Solved 2020]을 참조하여 유튜브 실시간 동영상을 MP4로 저장한다.

  1. C:\Program Files (x86)\VideoLAN\VLC\lua\playlist 디렉토리 youtube.luac 파일을 삭제하고 youtube.lua 파일을 youtube.luac 파일로 대체시킨다.
  2. VLC → 도구 → 코덱 → 코덱 탭에서 “위치”를 복사한다.
  3. 구글 크롬 웹브라우저 주소창에 입력하여 동영상을 재생시킨다.
  4. 재생되는 동영상에 마우스 우클릭으로 “동영상을 다른 이름으로 저장” 해서 MP4 파일로 로컬 컴퓨터로 저장시킨다.

2 MP4 → 오디오 파일 변환

유튜브 주소를 가지고 .mp4 동영상을 로컬 파일로 갖게 되면 다음 단계로 오디오만 추출하여 .mp3로 저장시킨다.

  • VLC → 변환 /저장하기 → 하단, 변환하기 → 시작

상기 전체 과정이 마무리되면 결과물은 다음과 같다.

유튜브 동영상 MP4 동영상 MP3 오디오

3 정답: 대국민 담화문 전문

한겨레 신문사 “박근혜 대통령 3차 대국민담화 전문”을 담화문 전문 웹스크랩핑하여 텍스트 데이터로 준비한다.

library(tidyverse)
library(rvest)

hani_script_url  <- "http://www.hani.co.kr/arti/politics/bluehouse/772447.html"

hani_script <- hani_script_url %>% 
  read_html(encoding = "utf-8") %>% 
  html_node(xpath = '//*[@id="a-left-scroll-in"]/div[2]/div/div[2]') %>% 
  html_text() 

hani_script <- hani_script %>% 
  str_remove_all(pattern = "\\n") %>% 
  str_trim()

hani_script
[1] "존경하는 국민 여러분. 저의 불찰로 국민 여러분께 큰 심려를 끼쳐드린 점 다시 한 번 깊이 사죄드립니다. 이번 일로 마음 아파하시는 국민 여러분의 모습을 뵈면서 저 자신 백번이라도 사과를 드리는 것이 당연한 도리라고 생각하고 있습니다. 하지만 그런다 해도 그 큰 실망과 분노를 다 풀어드릴 수 없다는 생각에 이르면 제 가슴이 더욱 무너져 내립니다.  국민 여러분. 돌이켜보면 지난 18년 동안 국민 여러분과 함께 했던 여정은 더없이 고맙고 소중한 시간이었습니다. 저는 1998년 처음 정치를 시작했을 때부터 대통령에 취임하여 오늘 이 순간에 이를 때까지 오로지 국가와 국민을 위하는 마음으로 모든 노력을 다 해왔습니다. 단 한 순간도 저의 사익을 추구하지 않았고 작은 사심도 품지 않고 살아 왔습니다.  지금 벌어진 여러 문제들 역시 저로서는 국가를 위한 공적인 사업이라고 믿고 추진했던 일들이었고, 그 과정에서 어떠한 개인적 이익도 취하지 않았습니다. 하지만 주변을 제대로 관리하지 못한 것은 결국 저의 큰 잘못입니다. 이번 사건에 대한 경위는 가까운 시일 안에 소상히 말씀을 드리겠습니다.  국민 여러분, 그 동안 저는 국내외 여건이 어려워지고 있는 상황에서 나라와 국민을 위해 어떻게 하는 것이 옳은 것인지 숱한 밤을 지새우며 고민하고 또 고민하였습니다. 이 자리에서 저의 결심을 밝히고자 합니다.  저는 제 대통령직 임기 단축을 포함한 저의 진퇴 문제를 국회의 결정에 맡기겠습니다. 여야 정치권이 논의하여 국정 혼란과 공백을 최소화하고 안정되게 정권을 이양할 수 있는 방안을 만들어 주시면 그 일정과 법 절차에 따라 대통령직에서 물러나겠습니다.  저는 이제 모든 것을 내려놓았습니다. 하루속히 대한민국이 혼란에서 벗어나 본래의 궤도로 돌아가길 바라는 마음 뿐입니다. 다시 한 번 국민 여러분께 진심으로 죄송하다는 말씀을 드리며 대한민국의 희망찬 미래를 위해 정치권에서 지혜를 모아주실 것을 호소드립니다.  (기자 질문)  공범 관계 인정하지 않으시는 겁니까?(박 대통령)  여러가지 무거운 말씀을 드렸기 때문에 다시 말씀드렸듯이 여러가지 경위에 대해 소상히 말씀드리겠고 다시 한 번 질문하고 싶은 것도 해주시면 좋겠다."

4 오디오 → 텍스트

Google Cloud Speech-to-Text 활용을 사용하면 1분 이하 (59초까지) 무료로 MP3 파일을 올려 텍스트를 추출할 수 있다.

본격적으로 googleLanguageR 팩키지를 사용해서 음성이 담긴 MP3 파일에서 텍스트를 추출해보자. 구글 클라우드 콘솔로 이동해서 다운로드 받은 인증 json 파일을 GL_AUTH 환경변수명을 .Renviron 파일에 등록시킨다.

  • $private_key 가 포함된 Credential은 “Service Accounts” 에서 .json 파일을 다운로드받아 환경설정한다.
    • error was: $private_key not found in JSON
  • googleAuthR::gar_auth_service()을 통해 한번 더 인증과정을 거친다.
    • No .httr-oauth file exists in current working directory.

1분 이하만 구글 Speech to Text 를 받기 때문에 1분간격으로 파일을 쪼개 각각을 TTS 한다.
MP3 파일을 받지 않기 때문에 FLAC 파일 형태로 취하고 FLAC 파일에서 지정된 audio_channel_count 갯수를 맞춰준다.

library(googleLanguageR)

# 환경설정
readRenviron("~/.Renviron")

# No .httr-oauth  file exists in current working directory. 문제 해결
# googleAuthR::gar_auth_service("~/youtube-xxxxx-xxxxxx200426574.json")

kt_config <- list(encoding = "FLAC",
                  audioChannelCount = 2,
                  diarizationConfig = list(
                    enableSpeakerDiarization = TRUE
                  ))

script_01_obj <- gl_speech("data/park_03_flac (mp3cut.net) (1).flac", languageCode = "ko-KR", customConfig = kt_config)
script_02_obj <- gl_speech("data/park_03_flac (mp3cut.net) (2).flac", languageCode = "ko-KR", customConfig = kt_config)
script_03_obj <- gl_speech("data/park_03_flac (mp3cut.net) (3).flac", languageCode = "ko-KR", customConfig = kt_config)
script_04_obj <- gl_speech("data/park_03_flac (mp3cut.net) (4).flac", languageCode = "ko-KR", customConfig = kt_config)
script_05_obj <- gl_speech("data/park_03_flac (mp3cut.net) (5).flac", languageCode = "ko-KR", customConfig = kt_config)


whole_script <- glue::glue("{script_01_obj$transcript$transcript}",
                           "{script_02_obj$transcript$transcript}",
                           "{script_03_obj$transcript$transcript}",
                           "{script_04_obj$transcript$transcript %>% na.omit()}",
                           "{script_05_obj$transcript$transcript  %>% na.omit()}")

stt_script <- whole_script %>% 
  str_remove_all(pattern = "[a-zA-Z]") %>% 
  str_c(collapse = " ")

stt_script %>% 
  write_lines("data/stt_script.txt")
stt_script <- read_lines("data/stt_script.txt")
stt_script
[1] "존경하는 국민 여러분 저의 불찰로 국민 여러분께 큰 심려를 끼쳐드린 점 다시 한번 깊이 사죄드립니다 이번 일로 마음 아파 하시는 국민 여러분의 모습을 보면서 저자신 백번이라도 사과를 드리는 것이 당연한 둘이라고 생각하고 있습니다 하지만 그런다 해도 그 큰 실망과 분노를 다 풀어 드릴 수 없다는 생각에 이르면정은 더없이 고맙고 소중한 시간이었습니다 저는 1998년 처음 정치를 시작했을 때부터 대통령에 취임하여 오늘이 순간에 이르기까지 오로지 국가와 국민을 위하는 마음으로 모든 노력을 다해 왔습니다 단 한순간도 저의 사익을 축구 하지 않았고 작은 사심도 품지 않고 살아 왔습니다안 왔습니다 하지만 주변을 제대로 관리하지 못한 것은 결국 저에게 큰 잘못입니다 이번 사건에 대한 경위는 가까운 시일 안에 소상이 말씀을 드리겠습니다 국민 여러분 그동안 저는 국내에 국내외 여건이 어려워지고 있는 상황에서 나라와 국민을 위해 어떻게 하는 것이 옳은 길인지 숱한 밤을 지새우며 고민하고 또 고민하였습니다운영직 임기 단축을 포함한 진퇴 문제를 국회의 결정에 맡기겠습니다 여야 정치권이 논의하여 국정의 혼란과 공백을 취소하고 안정되게 정권을 이용할 수 있는 방안을 만들어 주신 그 일정과 법 절차에 따라 대통령직에서 물러나겠습니다양찬 미래를 위해 정치권에서도 지혜를 모아 주실 것을 호소드립니다 제 가슴이 더욱 무너져 내립니다 국민 여러분 돌이켜보면 지난 10년 동안 국민 여러분과 함께 했던지금 벌어진 여러 문제들 역시 저로서는 국가를 위한 공적인 사업이라고 믿고 추진했던 일들이 없고 그 과정에서 어떠한 개인적 이익도 취하지이제 저는이 자리에서 저의 결심을 밝히고자 합니다 저는 제저는 이제 모든 것을 내려놓았습니다 하루속히 대한민국이 혼란에서 벗어나 본래의 궤도로 돌아가기를 바라는 마음뿐입니다양찬 미래를 위해 정치권에서도 지혜를 모아 주실 것을 호소드립니다  다시 한 번 국민 여러분께 진심으로 죄송하다는 말씀을 드리며 대한민국의양찬 미래를 위해 정치권에서도 지혜를 모아 주실 것을 호소드립니다"

5 담화문과 STT 비교

마지막으로 대국민 담화문 원문과 구글 STT 결과 작업결과를 비교해보자.

library(diffr)

original_script <- tempfile()
writeLines(hani_script, con = original_script)
google_stt_script <- tempfile()
writeLines(stt_script, con = google_stt_script)


diffr(original_script, google_stt_script, before = glue::glue("대국민 담화문 원문"), after = glue::glue("구글 STT 작업결과"))