CNNをベースとした音声区間分割 inaSpeechSegmenter を使ってみた

# はじめに
- 音声ファイルの分割をしたい(久しぶりに音声の話題なのは(ry
- Pydubでもできるけど，パラメータを考えるのが面倒くさい
- 今回紹介するものはシンプルな作りをしている
- 区間ごとにラベル付けをしたり，一応性別検出もしてくれる
- [Pythonの音声区間検出ライブラリ inaSpeechSegmenterを試してみた話](http://tam5917.hatenablog.com/entry/2020/01/25/132113)@先駆者様感謝



# 実行環境
今回試した環境は以下の通りです．
OS: Ubuntu 18.04 LTS
CPU: i3-4130 3.40GHz
メモリ: 16GB
GPU: GeForce GTX 1660 Ti (6GB)
Python : 3.6.9

# 1. inaSpeechSegmenterのインストール
本家通りに実行すれば，基本は問題ありません．
https://github.com/ina-foss/inaSpeechSegmenter

加えて必要となるものを以下にまとめて列挙します．
※仮想環境で作成することを推奨します.ex) virtualenv, singularity etc...


```
$ sudo apt-get -y install ffmpeg
$ sudo apt-get -y install python3-tk
$ pip3 install tensorflow-gpu # GPUがある人向け
$ pip3 install tensorflow # GPUがない人向け
$ pip3 install inaSpeechSegmenter
```

インストール出来ればおｋです．

# 2. Audio Segmentation
今回参考にした[サイト](http://tam5917.hatenablog.com/entry/2020/01/25/132113)をベースにしてスクリプトを作成しました．



```audioSeg.py
# -*- coding: utf-8 -*-
# Audio Segmentation Using inaSpeechSegmenter
# Original: https://gist.github.com/tam17aki/11eb1566a2d48b382607d23dddb98891

# How To Use
# python3 audioSeg.py [inputfile] [output_dir]

from inaSpeechSegmenter import Segmenter
from inaSpeechSegmenter import seg2csv
from pydub import AudioSegment
import os
import sys

# コマンドラインの数を確認
if len(sys.argv) != 3:
    print("python3 audioSeg.py [inputfile] [output_dir]")
    sys.exit()

# 入力のwavファイルの絶対パスを指定
input_file = os.path.abspath(sys.argv[1])

# 出力のwavファイルのディレクトリを指定
if not os.path.exists(sys.argv[2]):
        os.mkdir(sys.argv[2])
        print("make dir",sys.argv[2])

output_dir = os.path.abspath(sys.argv[2])

# 'smn' は入力信号を音声区間(speeech)、音楽区間(music)、ノイズ区間(noise)にラベル付けしてくれる
# detect_genderをTrueにすると、男性(male) / 女性(female)のラベルに細分化されるが、処理速度は遅くなる
seg = Segmenter(vad_engine='smn', detect_gender=False)

# 区間検出実行（たったこれだけでOK）
segmentation = seg(input_file)

# ('区間ラベル',  区間開始時刻（秒）,  区間終了時刻（秒）)というタプルが
# リスト化されているのが変数 segmentation
# print(segmentation)

# inaSpeechSegmenter単体では分割されたwavを作成してくれないので、
# pydubのAudioSegmentにお世話になる (ありがたいライブラリ)
speech_segment_index = 0
for segment in segmentation:
    # segmentはタプル
    # タプルの第1要素が区間のラベル
    segment_label = segment[0]

    if (segment_label == 'speech'):  # 音声区間

        # 区間の開始時刻の単位を秒からミリ秒に変換
        start_time = segment[1] * 1000
        end_time = segment[2] * 1000

        # 分割結果をwavに出力
        newAudio = AudioSegment.from_wav(input_file)
        newAudio = newAudio[start_time:end_time]
        newAudio.export(output_dir +"/segment"+ str(speech_segment_index), format="wav")

        speech_segment_index += 1
        del newAudio

# 区間ごとのラベル,開始時間,終了時間をcsv形式で保存
seg2csv(segmentation, 'segResult.csv')
```

スクリプト上にも示していますが，実行例を示します．
※色々WARNINGは出ると思いますが，無視しておｋです．

```
$ python3 audioSeg.py input.wav output_dir
```

出力される内容は以下の通りです．

- output_dir: 音声区間(speech)と検出された音声ファイルが保存されているディレクトリ
- segResult.csv: 入力音声に対して，区間ごとにラベル，開始時間，終了時間が保存されているcsvファイル
    - ラベル：speech, music, noise, noEnergyの4種類
        - genderをTrueにすると，speechがmaleとfemaleに変更され，5種類になる（処理は遅くなる）

実際に私が試しにラジオ音声でやってみたところ，音の重なりがないところは比較的良いラベル付けがされていたと思います．
要は音楽区間は音楽，音声区間は音声とラベル付けされていたということです．
感想としては，少なくとも無音区間の分割手法より音声区間を切り出せていたと思います．
# Ex. Audio Segmentation@性別検出用の変更点
正直いらないと思いますが，上記のスクリプトからの変更点を示します．

```audioSegEx.py

# この部分のdetect_genderをTrueにすると性別検出が可能
seg = Segmenter(vad_engine='smn', detect_gender=True)

-------------------------------------------------------
# 男性と女性の検出部分(male,femaleに設定)
if (segment_label == 'male'):
if (segment_label == 'female'):
```

性別検出に関しては少なくても良い精度とは言えないと思います．
試しに男女1人ずつのラジオ音声でしてみると，2人の音声が重なることが多いため，ラベル付けがうまくできていませんでした．
1人ずつ喋っている場合ならもう少し良くなると思います．
# まとめ

- inaSpeechSegmenterを用いて音声区間の分割を行った．
- Pydubのsplit_on_silenceよりかは使えそう．
- 音声データ作成の一助になれば幸い．


# 参考文献
[CNN-based audio segmentation toolkit. Allows to detect speech, music and speaker gender. Has been designed for large scale gender equality studies based on speech time per gender. ](https://github.com/ina-foss/inaSpeechSegmenter)
[Pythonの音声区間検出ライブラリ inaSpeechSegmenterを試してみた話](http://tam5917.hatenablog.com/entry/2020/01/25/132113)
[【Python/pydub】mp3、wavファイルの分割（無音部分で区切る） ](https://algorithm.joho.info/programming/python/pydub-split-on-silence/)