Skip to content

Instantly share code, notes, and snippets.

@DDRBoxman
Created August 3, 2024 17:57
Show Gist options
  • Save DDRBoxman/46f6dd6bac813e12966216123c312955 to your computer and use it in GitHub Desktop.
Save DDRBoxman/46f6dd6bac813e12966216123c312955 to your computer and use it in GitHub Desktop.
Anki add matched audio files
from aqt import mw
from aqt.qt import *
from anki.hooks import addHook
import os
import unicodedata
def add_media_to_cards(deck_name, field_name, media_folder, target_field):
# Function to normalize Unicode strings
def normalize(s):
return unicodedata.normalize('NFC', s)
# Get the deck ID
deck_id = mw.col.decks.id(deck_name)
if not deck_id:
raise ValueError(f"Deck '{deck_name}' not found.")
# Get the cards in the deck
card_ids = mw.col.db.list("select id from cards where did = ?", deck_id)
if not card_ids:
raise ValueError("No cards found in the specified deck.")
# Preload media files dictionary with normalized names
media_files = {}
for filename in os.listdir(media_folder):
base_name, ext = os.path.splitext(filename)
if ext.lower() not in ['.mp3', '.wav', '.ogg']:
continue
normalized_name = normalize(base_name.split(" - ", 1)[-1])
media_files[normalized_name] = filename
# Print loaded media files for debugging
print("Loaded media files:", media_files)
# Iterate over each card
for cid in card_ids:
card = mw.col.get_card(cid)
note = card.note()
# Get the content of the specified field
if field_name not in note:
continue # Skip cards without the field
field_value = normalize(note[field_name].strip())
if not field_value:
continue # Skip cards with an empty field
# Debugging: Print the field value being searched
print(f"Searching for file containing '{field_value}'")
# Find the file match
matched_file = None
for normalized_name, filename in media_files.items():
if field_value in normalized_name:
matched_file = os.path.join(media_folder, filename)
break
if matched_file:
# Debugging: Print the found file path
print(f"Found file '{matched_file}' for '{field_value}'")
# Add the file as media to the card
try:
stored_filename = mw.col.media.add_file(matched_file)
note[target_field] = f"[sound:{stored_filename}]"
except Exception as e:
print(f"Error adding media file '{matched_file}': {e}")
else:
print(f"File for '{field_value}' not found in '{media_folder}'.")
# Save changes to the note
try:
mw.col.update_note(note)
except Exception as e:
print(f"Error updating note for field value '{field_value}': {e}")
# Example usage:
def on_run_action():
deck_name = "Pokemon Names"
field_name = "Japanese"
media_folder = "/Users/ddrboxman/Downloads/日本語/"
target_field = "Pronunciation" # Updated to the correct target field
try:
add_media_to_cards(deck_name, field_name, media_folder, target_field)
QMessageBox.information(mw, "Success", "Media added to cards successfully.")
except Exception as e:
QMessageBox.critical(mw, "Error", str(e))
# This will add a menu item to run your script from the Tools menu
def add_menu_item():
action = QAction("Add Media to Cards", mw)
action.triggered.connect(on_run_action)
mw.form.menuTools.addAction(action)
addHook("profileLoaded", add_menu_item)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment