youtubeやニコニコのURLを入力するとその動画の音声をダウンロードして、音声を文字起こしAI「Whisper」で文章化し出力するツールを作成しました。
DiscordのBOTとして実装しておいたので、出先でも簡単に扱えます!
1,事前準備 必要なもの諸々
まずPython3.10をインストール
当方で動作確認が取れているのはPython3.10.7のためそれをインストールしていますが、多分マイナーバージョンまでは合わせなくても大丈夫です。
Pythonがまだインストールされていない方は以下の手順に従ってPythonをWindowsにインストールしてください。
PythonのインストールとPTATHへの追加が終わっている前提で次に進みます。
次は必要なモジュールをいくつかpip installコマンドでインストールしていきます。
次に必要なモジュールをpipでインストール
コマンドプロンプトにコマンドをコピペしてエンターキーを押してください。
コマンドプロンプトはWindowsキーを押した後、「cmd」と打ち込みエンターキーを押すと起動できます。
管理者権限は不要です。

まずYoutubeダウンローダー「yt-dlp」をインストールします。
(Youtube-dlは遅いので勧めません。yt-dlpのほうが10倍以上高速です)
pip install yt-dlp
次に文字起こしAI「Whisper」をインストールします。
pip install git+https://github.com/openai/whisper.git
Whisperの動作要件は「ffmpeg」「Pytorch」がインストールされていることのため、まだの方はその2つもインストールします。
PyTorchについてはCUDAバージョンなどに左右されるため、エラーなど出たら公式を確認してください。

ここでは一例として当方の環境(上記画像の通り)のコマンドを載せておきます。
pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu117
FFmpegのインストールはこの記事を参考にしてください。
では動かしていきます。
2,処理本体
ようつべダウンロード部分
このコードをyoutube-dl.pyなど名前を付けて保存してください。
URLに文字起こししたい動画のURLを入れて実行すると、そのpyファイルと同じディレクトリに動画の名前のm4aファイルが保存されます。
import yt_dlp
URLS = ["https://www.youtube.com/watch?v=VWVtIg5cdDU"]
ydl_opts = {
"format": "m4a/bestaudio/best",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "m4a",
}
],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
error_code = ydl.download(URLS)
文字起こし部分
import whisper
model = whisper.load_model("base")#モデル名指定
result = model.transcribe("test.mp3")#音声ファイル名
print(result["text"])
Whisperは超簡潔なコードで動くので楽ちんですねぇ。

モデルは当然サイズがデカいほど精度が良いですが、時間とVRAMの必要量も増します。
今回はDiscordBOT化するため速度重視でいきます。「base/small」あたりが手軽で良いと思います。
その他処理
ダウンロード時音声ファイル名を指定する方法がよくわからないので、フォルダ内の.m4aファイル名を取得して、Whisperの処理対象ファイル名とします。
import glob
import os
file_list = glob.glob(
"C:/Users/loveanime/Desktop/youtube2text/*.m4a"
) # スクリプトを置いたフォルダ内に保存された音声ファイル名取得
name_list = [os.path.basename(file) for file in file_list]
audio_name=name_list[0]
print(audio_name)
処理後にその音声ファイルを削除するようにするのでname_list[0]で大丈夫です。
繋げるとこのようになる
import glob
import os
import yt_dlp
import whisper
URLS = ["https://www.youtube.com/~"] #動画のリンク
ydl_opts = {
"format": "m4a/bestaudio/best",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "m4a",
}
],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
error_code = ydl.download(URLS)
file_list = glob.glob(
"C:/Users/loveanime/Desktop/youtube2text/*.m4a"
) # スクリプトを置いたフォルダ内に保存された音声ファイル名取得
name_list = [os.path.basename(file) for file in file_list]
audio_name = name_list[0]
model = whisper.load_model("small")
result = model.transcribe(audio_name)
print(result["text"])
os.remove(audio_name)
実行するとこの通り。

採点してみるとそこそこの精度出ていますね。
ただ実用性を考えるとmedium以上のほうが良いかも……
色は似合えどいつか散りのうを 彷徨うことさえ 許せなかな咲き誇る名前はいつか 教えてくれた 生きるだけではずわみと離れられない 離せはしない一人だけ想いは心も戻せるばかり色は似合えどいつか散りのうを 彷徨うことさえ 許せなかな甘える誘わせと甘えられたで 初めが優しく(以下略)
コード編集にはVScodeがおすすめです。
便利な拡張機能を布教しているので是非合わせてご覧ください!!
3,応用編:DiscordBOTに組み込んだ
コピペOK! 実際のコード
DiscordのBOTの申請などの方法は省略します。
実際のコードがコチラ
import os
import re
import glob
import discord
import torch
import yt_dlp
import whisper
# 接続に必要なオブジェクトを生成
client = discord.Client(intents=discord.Intents.all())
@client.event # 起動時に動作する処理
async def on_ready():
"""起動したらターミナルにログイン通知が表示される"""
print("ログインしました")
@client.event # 発言時に実行されるイベントハンドラ定義
async def on_message(message):
"""実際に応答する箇所"""
if client.user in message.mentions: # 話しかけられたかの判定
await reply(message) # 返信する非同期関数を実行
# ボット自身を除外
if message.author.bot:
return
# 全角を半角に一律で置換 元の文字列の変換テーブル
tables = str.maketrans(
"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`>?@abcdefghijklmnopqrstuvwxyz{|}~",
"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`>?@abcdefghijklmnopqrstuvwxyz{|}~",
) # 変換("を"にするのだけはできない)
message.content = message.content.translate(tables)
# yt_dlp & whisper
words = ["!y2t"]
for word in words:
if word in message.content:
url = message.content
url = re.search(r"http.*", url, flags=re.DOTALL)
url = url.group(0) # メッセージからhttpを含むhttp以下の文字を取り出してURLにしている
URLS = [url]
ydl_opts = {
"format": "m4a/bestaudio/best",
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "m4a",
}
],
}
await message.channel.typing()
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
error_code = ydl.download(URLS) # ここまでyt_dlp
file_list = glob.glob(
"C:/discode_bot/*.m4a"
) # スクリプトを置いたフォルダ内に保存された音声ファイル名取得
name_list = [os.path.basename(file) for file in file_list]
audio_name = name_list[0] # ここで音声ファイル名取得
await message.channel.send("Please wait for a few minites.")
model = whisper.load_model("small") # Whisper
result = model.transcribe(audio_name)
if len(result["text"]) <= 2000:
await message.channel.send(result["text"])
else:
await message.channel.send(
"__character length is over 2000,so I can't send you.__"
)
os.remove(audio_name)
# 処理ここまで
# 起動とDiscordサーバーへの接続
client.run("AAAAAAAAAAAAAAAA12345678909876543321")#トークン
挙動など
上記コードを実行すると、このようになります。

「!y2t https://www.youtube.com/watch?~」と入力すると動画の文字が書き出されていることがわかります。
ちなみにy2tはyoutube2(to)textの略です。
当方の3090では1分の動画の処理におよそ30秒かかりました。

ここではsmallを使用しているため理論上10秒余りで文字起こし処理自体は終了しますが、URL先の動画のダウンロード処理や、文字の送信などにより計30秒かかったのだと思われます。
ちなみにyt_dlpはYou Tube専門みたいな名前しておきながらニコニコ動画などもダウンロードできます。

つまりニコ動文字起こしもできる!!
まとめ Youtubeやニコ動を文字起こしAI「Whisper」で文章にするツール作成備忘録
python3.10と以下をインストールしておきます。
(pip)はpip installでインストールできるモジュールを指します。
- yt-dlp(pip)
- ffmpeg(手動)
- pytorch(pip)
- whisper(pip)
- (discord(pip))

あとは適切なサイズのモデルをセレクトして、コピペ用コードを動かすだけ!!
DiscordBOTやPython関連のその他記事もご覧ください!