この記事では既存のAnkiのデッキにある単語全てに自動で音声を追加するコードを共有します。
Ankiで英語単語を登録して勉強しているけど、音声があると嬉しいという方を対象にしています。
開発経緯
現在はAnkiは完全に自動化しており、Discordにメッセージを送ったら音声、意味、例文をネットで検索して自動で追加できるようにプログラミングを組んでいます。
詳しくは下記の記事で読めます。
ですが、自動化する以前から使用しているのでその前に登録したカードには音声は登録されていません。
今回はその単語たちにも音声を追加するためにPythonでコードを書いてみることにしました。
ソースコード
import requests
import json
from gtts import gTTS
from bs4 import BeautifulSoup
import string
import shutil
import os
import re
ANKI_MEDIA_DIR = "/Users/user_name/Library/Application Support/Anki2/User 1/collection.media"
# AnkiConnectを使ってノートを取得
def get_notes(deckName):
return requests.post('http://localhost:8765', json={
'action': 'findNotes',
'version': 6,
'params': {
'query': f'deck:{deckName}',
}
}).json()
# ノートの情報を取得
def get_note_info(noteId):
return requests.post('http://localhost:8765', json={
'action': 'notesInfo',
'version': 6,
'params': {
'notes': [noteId],
}
}).json()
# ノートの内容を更新
def update_note(noteId, front):
requests.post('http://localhost:8765', json={
'action': 'updateNoteFields',
'version': 6,
'params': {
'note': {
'id': noteId,
'fields': {
'Front': front,
},
},
},
})
def contains_japanese(text):
"""Check if the text contains Japanese characters."""
return bool(re.search('[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uff66-\uff9f]', text))
# 音声を生成して追加
def add_audio(deckName):
note_ids = get_notes(deckName)['result']
for note_id in note_ids:
note_info = get_note_info(note_id)['result'][0]
front_html = note_info['fields']['Front']['value']
# HTMLタグを除去して音声タグを取り除く
soup = BeautifulSoup(front_html, 'html.parser')
for tag in soup.find_all("audio"):
tag.decompose()
front = soup.get_text().strip()
# 既に音声が追加されている場合はスキップ
if "[sound:" in front_html or contains_japanese(front):
continue
# テキストから音声を生成
try:
tts = gTTS(front, lang='en')
except Exception as e:
print(f"Unable to generate sound for {front}: {e}")
continue
# ファイル名に使えない文字を除去
valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits)
filename = ''.join(c for c in front if c in valid_chars)
audio_file = f'{filename}.mp3'
tts.save(audio_file)
# ファイルをAnkiのmediaディレクトリに移動
shutil.move(audio_file, os.path.join(ANKI_MEDIA_DIR, audio_file))
# ノートを更新して音声を追加
front_with_audio = f'{front} [sound:{audio_file}]'
update_note(note_id, front_with_audio)
# デッキの名前を指定
deckName = 'your_deck'
add_audio(deckName)
以下の2 つはご自身のAnkiメディアパスとデッキ名を入れてください。
ANKI_MEDIA_DIR =
deckName =
ANKI_MEDIA_DIRのパスはOSによって違うので注意してください。
以下はOSごとの一般的なパスの場所です。
Windows: C:\Users\<YourUserName>\AppData\Roaming\Anki2\<YourProfileName>\collection.media
macOS: /Users/<YourUserName>/Library/Application Support/Anki2/<YourProfileName>/collection.media
Linux: ~/Documents/Anki/<YourProfileName>/collection.media
条件、仕様
・Front面に英単語のみが記載されている
・Frontに日本語だった場合はスキップされます
・音声の2重登録を避けるために既に音声が登録されているカードはスキップする
音声取得にはgtts(Google Text-to-Speech)を使用しました。
gttsはPythonのライブラリで、Googleのテキスト-音声変換エンジンを使用して、テキストから音声を生成する機能を提供しています。
カードのレイアウトなどは人によって違うかもしれないのでお好みでコードを改変してください。
いつもAnkiの自動化ばかり書いているので今回はかなり簡単に書くことができました。