astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

社内Podcastはじめました〜文字起こし〜形態素解析

ご挨拶

どうもお久しぶりです、gucciです。
入社してついに3年目に突入しました。信じられません。
まだまだ力不足な私ですが、周りの人に支えられてなんとかここまでやって参りました。
新しい仲間もどんどんと増え、これからは支える立場になれるように日々精進して参ります。

さて、今回は社内コミュニケーション活性化プロジェクトそれを使ったある分析をご紹介したいと思います。

以前axtstarさんが書かれた、この記事にあるような社内イベントが昨年の9月に再び開催されました。

lab.astamuse.co.jp

我がJチームが提案し、見事3位に選ばれ実現したプロジェクトが「Podcast」です。
弊社は今どんどんと新しい人がジョインしてきていて、どんどんと成長してきています。
新しい仲間が増えるのは大変嬉しいことですが、新しい仲間が増えると、
「あの人ってどんな人なんだろう、どんな趣味をお持ちなんだろう。」
「あ〜顔はなんとなく覚えたけど名前がすぐ出てこないな〜」
こんなことはよくあると思います。

そんな課題を全て解決してくれるのが、Podcastです。
f:id:astamuse:20200205131922p:plain 内容としては主に「新人さんいらっしゃい」というメインコーナーを据え、
アスタミューゼに入社された新人さんをゲストにお招きし、根掘り葉掘り話を聞くことでその魅力を引き出し、社内コミュニケーションの活性化を目指すという企画です。
(※注:Podcastとは言っていますが、Podcastのアプリから聞けるわけではなくあくまで社内向けに録音した音声ファイルを社内で発信している現状です)

もちろん任意での参加ですし、事前にちょっとした質問票に回答いただくことで、
軽快なトークが持ち味のDJトッキー切れ味鋭いツッコミが秀逸なMCスミィ(どちらも弊社社員です)がゲストの新人さんを丸裸にし、その人の魅力をどんどん引き出していきます。

なるべく手間をかけず良い物を提供するをモットーにしていますので、 マイクを立ててサウンドチェックして…などはせずに、iPhoneのボイスメモアプリで録音!
本番中ちょっと間違えちゃってもリテイクはなし!録音した音源を少し編集したらはい完成!
それでも内容はすごい充実っぷりです。
「面白過ぎてコーヒーを吹いた」「家族と聞いてたら『いい会社だね』と言ってもらえた」などご紹介しきれないぐらいの高評価をこれまでいただいております。

チームメンバーはいろんな部署から集まった個性派集団たちで、とても楽しく活動できております。
そんなチーム内での私の担当は、ミキサー(いわゆる音源編集)をしておりまして、簡単なBGMを入れたりする程度。
ちなみに作業画面はこんな感じ↓↓

f:id:astamuse:20200205111115p:plain
mixing
ゆくゆくは専用のラジオブースを設け、世界へと発信していけたら・・・という野望を抱いております。

さて、せっかく手元に生の音源があるのならばそれを生かして何かできないだろうかということで、
今回は録音音源を用いて、はじめての「文字起こし」はじめての「形態素解析」をやってみたいと思います!
(ちょいちょいハマったポイントがあるので、ハマった箇所は最後にまとめてあります)

文字起こし

今回使ってみるのは、GoogleのAPI「Google Speech-to-Text」です。
機械学習を利用して音声をテキストに変換してくれちゃうというAPIですね。

cloud.google.com

簡単なトライアルもありますのでよかったら試してみてください。
これがなかなか精度が良いとの噂を聞き、使ってみることにしました。

Google Speech-to-Textを使って、Podcastの音源を文字起こしするのにあたりいくつかの不安点がありました。

  1. お金がかかる(API使用などの費用の問題)
  2. iPhoneの内臓マイクで録音しているため、音質がよくない(音源データの音質の問題)
  3. 複数人が同時に喋ることがある(そもそも複数人は対応できないのではという問題)

1は、Google Cloud Platformの無料枠というのが12 か月間 300ドル分あるので、それを使うことで解決!とてもありがたいですね。使い倒してやりましょう。

cloud.google.com

2は録音環境の問題なので現状では改善のしようがないため、ダメだったら仕方がない!
3も同様に、ダメだったら仕方がない!

それでは、レッツ文字起こし。
初めてのGCEのインスタンス作成も、有識者の方々がたくさん記事を挙げてくれているのであまり苦しむことなく無事に作れました。
GCEのインスタンス作成→Google Speech-to-Text APIの有効化→音源ファイルを配置するGCSバケットの作成 といったことをやりました。

Google Speech-to-TextのAPIは、以下の3種類があります。

  • 短い音声ファイルの同期音声認識
  • 長い音声ファイルの非同期音声認識
  • ストリーミング入力のリアルタイム音声認識

今回はPodcast音声が1回あたり約30分なので非同期音声認識「長い音声ファイルの文字変換」を行います。

cloud.google.com

このあたりもネットに良い記事がいくつかあるのでそちらを参考にして、

# !/usr/bin/env python
# coding: utf-8
import argparse
import io
import sys
import codecs
import datetime
import locale

def transcribe_gcs(gcs_uri):
    from google.cloud import speech
    from google.cloud.speech import enums
    from google.cloud.speech import types
    client = speech.SpeechClient()

    audio = types.RecognitionAudio(uri=gcs_uri)
    config = types.RecognitionConfig(
        encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16, # 拡張子wavの設定
        sample_rate_hertz=44100, # 音声ファイルのヘルツ
        language_code='ja-JP') # 日本語の場合

    operation = client.long_running_recognize(config, audio)

    print('Waiting for operation to complete...')
    operationResult = operation.result()

    d = datetime.datetime.today()
    today = d.strftime("%Y%m%d-%H%M%S")
    fout = codecs.open('output{}.txt'.format(today), 'a', 'utf-8')

    for result in operationResult.results:
      for alternative in result.alternatives:
          fout.write(u'{}\n'.format(alternative.transcript))
    fout.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        'path', help='GCS path for audio file to be recognized')
    args = parser.parse_args()
    transcribe_gcs(args.path)

いざ!

$ python3 transcribe.py gs://[GCSのバケット名]/[音声データファイル名].wav

10分ほど待って、出力されたファイルをおそるおそる見てみると・・・ ※ハマりポイント1

新人さんいらっしゃいはアスタミューゼに入社された新人さんに根掘り葉掘り話を聞くことでその魅力を引き出し社内コミュニケーションの活性化を目指すオーナーです・・・

キタ━━━(゚∀゚)━━━ !!!!!
最後の部分、正しくは「コーナー」が「オーナー」になっているけど、きてますきてます。
30分のファイルでだいたい変換にかかる時間は10分ちょいってところです。いいですね。

ただ、やはり・・・不安点2と3の予想は的中しました。
変換されたテキストをみると、

  • 抜けている箇所がある
  • 変換がおかしくなっている
  • 複数人で重なって喋っているとゴソッとその部分が抜けている

というのが結構見受けられます。 また、あだ名のような固有名詞はそもそも登録されていないからか、DJトッキーがDJポッキーになったりしていますね。
だいたい文字起こしの精度としては2〜3割程度でしょうか。
元の会話を知っていれば理解できますが、知らないとちょっと何言ってるかわからないという文になっています。

今回来たって言わどうですかねもう秋にスーツ屋さんにしか見えない放射能と三宅のシグマの笑顔が見えのが新人さん

よくわかりませんね。
スーツも放射能も三宅もシグマも話していませんが、このような面白い結果の箇所がありました。

ただそれでもすごい!もっとぐちゃぐちゃになるかと思いました。さすがGoogleさん。
音質にも原因があると思いますので、精度の検証はまた別の機会にさせていただきたく思います。
もっと文字起こしの結果をご紹介したいのですが、パーソナルな内容が多々あるのでご理解くださいませ。
それじゃあ何のために文字起こししたんだい、と言われてしまうと思います。
そこで今回は、主に使われている単語は何だろなチェックをしてみたいと思います!

いわゆる、文章を形態素解析して頻出単語順に並べるってやつです。
これでDJトッキーとMCスミィがよく使う単語が明らかになれば・・・これを学ぶことであなたもラジオパーソナリティになれるかも!?

それではやってみましょう。

形態素解析

私は自然言語処理の知識も何もないど素人ですが、よろしくお願いします!
日本語の形態素解析といえば、そう、MeCabを使います。
MeCabには追加で新語辞書もあるみたいなのでそちらを使いたいと思います。

MeCabのインストール

$ sudo apt-get install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8

入ったか確認してみよう

$ mecab -h

新語辞書を入れてみよう

$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neolog
$ sudo ./bin/install-mecab-ipadic-neologd -n -a

-aオプションで全ての追加辞書をインストール(2GBくらいあるので注意) ※ハマりポイント2

[install-mecab-ipadic-NEologd] : Do you want to install mecab-ipadic-NEologd? Type yes or no.

と聞かれるのでyesと答えてください。

[install-mecab-ipadic-NEologd] : Usage of mecab-ipadic-NEologd is here.
Usage:
    $ mecab -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd ...

と出ればインストール完了!さっそくやってみましょう!
まずは新語辞書を使わずに普通にmecabコマンド

$ mecab
おはようございます、今日はいい天気ですね #入力文がこちら
おはよう    感動詞,*,*,*,*,*,おはよう,オハヨウ,オハヨー
ござい   助動詞,*,*,*,五段・ラ行特殊,連用形,ござる,ゴザイ,ゴザイ
ます  助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
、 記号,読点,*,*,*,*,、,、,、
今日  名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は 助詞,係助詞,*,*,*,*,は,ハ,ワ
いい  形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気  名詞,一般,*,*,*,*,天気,テンキ,テンキ
です  助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
ね 助詞,終助詞,*,*,*,*,ね,ネ,ネ
EOS

うおおおおお形態素解析されてるうう。感動です。
続いて新語辞書に最近追加された「鬼滅の刃」という単語を使ってみます。
まずは新語辞書を使わずに・・・

鬼滅の刃が面白いらしいですね
鬼 名詞,一般,*,*,*,*,鬼,オニ,オニ
滅 名詞,一般,*,*,*,*,滅,メツ,メツ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
刃 名詞,一般,*,*,*,*,刃,ハ,ハ
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
面白い   形容詞,自立,*,*,形容詞・アウオ段,基本形,面白い,オモシロイ,オモシロイ
らしい   助動詞,*,*,*,形容詞・イ段,基本形,らしい,ラシイ,ラシイ
です  助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
ね 助詞,終助詞,*,*,*,*,ね,ネ,ネ
EOS

なるほど。ぶった切られている。 続いて新語辞書を使ってリトライ!

$ mecab -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd
鬼滅の刃が面白いらしいですね
鬼滅の刃    名詞,固有名詞,一般,*,*,*,鬼滅の刃,キメツノヤイバ,キメツノヤイバ
が 助詞,格助詞,一般,*,*,*,が,ガ,ガ
面白い   形容詞,自立,*,*,形容詞・アウオ段,基本形,面白い,オモシロイ,オモシロイ
らしい   助動詞,*,*,*,形容詞・イ段,基本形,らしい,ラシイ,ラシイ
です  助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
ね 助詞,終助詞,*,*,*,*,ね,ネ,ネ
EOS

すごいやん。ちゃんと一つの固有名詞として解析してくれました。
このように新語辞書は新しい単語を随時追加してくれているようです。ありがたや。
それではpythonでpodcastのテキスト文を形態素解析してみましょう!

python用のmecabライブラリのインストール ※ハマりポイント3

$ pip3 install mecab-python3

第6回配信までのPodcastを文字起こししたものを1つのファイルにまとめて、それをインプットに頻出単語順に並べてみます。

import MeCab
import sys
import re
from collections import Counter

with open("podcast_all.txt") as f: #文字起こししたpodcastデータの読み込み
  podcast = f.read()  

wakati = MeCab.Tagger("-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd") #新語辞書を適用
parse = wakati.parse(podcast)
lines = parse.split("\n")
items = (re.split("[\t,]", line) for line in lines)

#「EOS」と「空文字」と「ー」以外
words = [item[0] for item in items if (item[0] not in ("EOS", "", "ー"))]

## 標準出力に出力 ##########################
counter = Counter(words)
for word, count in counter.most_common():
  print(f"{word}: {count}")
の: 564
て: 489
に: 338
た: 311
です: 304
で: 278
は: 275
が: 256
と: 232
ね: 224
・
・
・

うおおおお・・・おぉぉ?ようわからんですね。
品詞の指定ができるのでしてみましょう。
名詞を指定し、さらに名詞の中の「一般」を指定してみます。以下に書き換えてもう一度。

#「EOS」と「空文字」と「ー」以外の「名詞」で「一般」のもの
words = [item[0] for item in items if (item[0] not in ("EOS", "", "ー") and item[1] == "名詞" and item[2] == "一般")]
人: 27
ゲスト: 25
皆さん: 24
番組: 24
コーナー: 17
新人: 15
自分: 15
魅力: 12
感じ: 12
家: 12
会社: 12
楽しみ: 9
社内: 9
次: 9
気: 9
感想: 9
コーヒー: 8
地元: 8
人生: 8
最後: 8
店: 8
理由: 7
気持ち: 7
音: 7
いらっしゃい: 6
コミュニケーション: 6
曲: 6
アスタミューゼ: 6
・
・
・

求めてやつ!そうそうこんなのが欲しかった! ついにたどり着きました。
せっかくなのでもう一歩だけ踏み込みます。

形態素解析して頻出単語を出せたので、それを使ってワードクラウドを作ってみましょう。

ワードクラウド とは
文章中で出現頻度が高い単語を複数選び出し、その頻度に応じた大きさで図示する手法。 ウェブページやブログなどに頻出する単語を自動的に並べることなどを指す。 文字の大きさだけでなく、色、字体、向きに変化をつけることで、文章の内容をひと目で印象づけることができる。

事前準備として、形態素解析した結果をテキストファイルに出しておきましょう。
wordcloudは文字列をスペース区切りで分割してカウントしていくようなので、さきほどの最後のコードを以下に書き換えて出力しておきます。

## ファイルに出力 #########################
out_path = "./wakati.txt"
with open(out_path, mode='w') as f:
  f.write(" ".join(words))

それではいざワードクラウドへ。
pythonならwordcloudのライブラリをインストールすれば簡単にできちゃいます。
(最終的にはpngファイルで出力するのでここからはmacで作業しています)

$ pip3 install wordcloud
from wordcloud import WordCloud

with open("wakati.txt") as f:  #形態素解析したデータを読み込む
  podcast = f.read() 

wordcloud = WordCloud(background_color="white",
    font_path="/System/Library/Fonts/ヒラギノ角ゴシック W3.ttc",
    width=800,height=600, colormap="jet", regexp=r"[\w']+").generate(podcast)

wordcloud.to_file("[お好きなパスにどうぞ]/wordcloud.png")

wordcloudは様々な設定ができるそうです。
フォントのパスはお使いのPCの日本語フォントのパスを指定してください。
幅や高さ、colormapまで変えられます。
wordcloudのデフォルトだと1文字はスキップしてしまうので、regexp=r"[\w']+"と指定しています。

そして出力した結果がこちら・・・

f:id:astamuse:20200205120408p:plain
podcast_wordcloud
とても見やすい。とてもそれっぽい!

ついにここまでたどり着きました。
我が社のPodcastは「人」という単語が一番登場するということが可視化されましたね。
やはり「人から着火しよう」というアスタミューゼの行動指針が根付いていますね。
さすがはDJトッキーとMCスミィです。

まとめ

いかがだったでしょうか。
文字起こしと形態素解析をはじめて挑戦してみましたが、とっても楽しいですね!
私のようにはじめてでも簡単にアウトプットを出すことができました。
GoogleAPIのすごさとpythonライブラリの素晴らしさを実感しました。
簡単に分析ができる環境が整っているからこそ、何をどう分析するのかが大事ということですね。

最後に、アスタミューゼではアプリエンジニア、デザイナー、プロダクトマネージャー、データエンジニア、機械学習エンジニアなどなど絶賛大募集中です! どしどしご応募ください!お待ちしております!

最後までお読みいただき、ありがとうございました!


ハマったポイント
ポイント1:モノラル音源データじゃないとだめ

ステレオ音源を文字起こししようとすると、

google.api_core.exceptions.InvalidArgument: 400 Must use single channel (mono) audio, but WAV header indicates 2 channels.

のエラーが基本的にはでます。
ただ、30分のpodcastデータを最初ステレオのまま文字起こししようとスクリプトを実行したら特にエラーがでることもなく 変換ファイルが出力されました。

ゲンタシン軟膏
ごめんね
真実への鍵をポストに入れて欲しい
シュメール文明
1070人組のソフト女の子
普通38中古
東照宮の行き方
香港ランニングウェア
ナガンヌ島シュノーケル
視聴率ランキング


文にすらなっていない・・・しかも、まったくこんな話していないのです。
「終わった。他にブログネタない、どうしよう。」と大慌てになったのはいい思い出です。
モノラル音源に変換して文字起こしをし直したところ、想定通りの結果になり一安心でした。
ある程度長いファイルになるとエラーが返せないのですかね?このあたりは謎でした。

ポイント2:メモリ不足

GCEの無料インスタンスであるfi-microではメモリ不足になりました。
g1-smallでもだめ。
n1-standard-1でようやくインストールできました。
2GBほどはメモリが必要ということですね。

ポイント3:swigが入ってないよ

error: command 'swig' failed with exit status 1

とでたら、

$ sudo apt install swig

と叩いてswigをインストールしてあげてください。


とっても参考になったURLたち
GCE無料枠での設定

これから始めるGCP(GCE) 安全に無料枠を使い倒せ - Qiita
GCE の無料枠のサーバを立るときに、初見でハマりそうなところ - Qiita

文字起こし

Google Cloud Speech API を使った音声の文字起こし手順 - Qiita
Google APIを使って音声ファイルを自動でテキストに文字起こしする - Qiita
Google Cloud Speech-to-Textのために音声をいろいろ加工して解析させてみた | ハックノート

MeCab

【Python3】MeCabでテキストファイルから名詞を頻出順に抽出 - Qiita
MecabをPythonで使うまで - Qiita
[Python]MeCabで誰でも簡単に分かち書きをする方法 | エンジニアの眠れない夜

WordCloud

Word Cloudで文章の単語出現頻度を可視化する。[Python] - Qiita
Pythonでテキストマイニング ②Word Cloudで可視化 - Qiita
Python - Word Cloud を作成する方法について - Pynote
【日本語文章の表示サンプルあり】Pythonのワードクラウドで使えるカラーマップ一覧✰ matplotlib/WordCloud✰ - なろう分析記録

Copyright © astamuse company, ltd. all rights reserved.