SHARE
TWEET
Fill audio field Anki plugin
a guest
Jul 31st, 2012
122
Never
- # -*- coding: utf-8 -*-
- """
- Fill audio field with [sound:$kana - $kanji.mp3]
- and try to download audio from languagepod101.
- If no audio available fill with no audio message.
- Skips over cards which already have something written
- in the audio field.
- """
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- import os, urllib, urllib2, shutil, hashlib
- from ankiqt import mw, ui
- from ankiqt.ui import utils
- from anki.cards import Card, Model
- # User settings
- """
- The name of the model. Other models will be ignored.
- """
- MODEL_NAME = 'MasterSentences'
- """
- The field which keeps the Kanji.
- """
- KANJI_FIELD = 'VocabularyKanji'
- """
- The field which keeps the Kana.
- """
- KANA_FIELD = 'VocabularyKana'
- """
- The field which keeps the audio.
- """
- AUDIO_FIELD = 'VocabularyAudio'
- """
- Content to fill with if audio is missing.
- """
- MISSING_FILL = u'(音無し)'
- # Internal settings
- audioFileExtension = '.mp3'
- downloadedFileExtension = '.php'
- base_url = 'http://assets.languagepod101.com/dictionary/japanese/audiomp3.php?'
- def downloadSound(kanji, kana, deck, log):
- """
- Download audio for given word. If it is not the dummy audio
- (check by file size) copy it to the media dir of the deck.
- """
- # Determine local file name
- target_filename = kana + u' - ' + kanji + u'.mp3'
- target_path = os.path.join(deck.mediaDir(create=True), target_filename)
- # Check if already present
- if os.path.exists(target_path):
- return 2
- # Download audo file
- args = urllib.urlencode({'kana': kana.encode('utf-8'), 'kanji': kanji.encode('utf-8')})
- url = base_url + args
- (filename, headers) = urllib.urlretrieve(url)
- # Check if not dummy audio
- size = os.path.getsize(filename)
- if(size > 50000):
- log.append('No audio for %s' % (kanji))
- return 3
- # Copy audio file
- shutil.copy2(filename, target_path)
- return 1
- def update_card(deck, card, log):
- """
- Update the card by reading kanji/kana, downloading the
- audio and updating the audio field.
- """
- kanji = card.fact[KANJI_FIELD]
- kana = card.fact[KANA_FIELD]
- audio = card.fact[AUDIO_FIELD]
- # Only update if no audio so far
- if audio.strip() == "" or audio.strip() == "<br />":
- status = downloadSound(kanji, kana, deck, log)
- if status == 1 or status == 2:
- newaudio = u"[sound:%s - %s.mp3]" % (kana, kanji)
- else:
- newaudio = MISSING_FILL
- card.fact[AUDIO_FIELD] = newaudio
- card.fact.setModified(textChanged=True,deck=deck)
- #log.append('Modified card %s[%s].' % (kanji, kana))
- return status
- else:
- #log.append('Did not modify card %s[%s].' % (kanji, kana))
- return 0
- def get_cards_from_deck(deck, log):
- """
- Gets all the card adhering to the model from the specified deck.
- """
- sql = 'select id from models where name = \'%s\'' % MODEL_NAME
- model_id = deck.s.scalar(sql)
- if model_id is None:
- log.append('No model of name %s' % MODEL_NAME)
- return []
- sql = 'select id from cardmodels where modelId = %s' % model_id
- card_model_ids = deck.s.column0(sql)
- cards = []
- for card_model_id in card_model_ids:
- cards_query = deck.s.query(Card).filter('cardModelId = %s' % card_model_id)
- for card in cards_query:
- cards.append(card)
- return cards
- def process_deck(deck, log):
- """
- Processes the cards in the specified deck.
- """
- cards = get_cards_from_deck(deck, log)
- total = 0
- modified = 0
- noaudio = 0
- for card in cards:
- total = total + 1
- status = update_card(deck, card, log)
- if status > 0:
- modified = modified + 1
- if status == 3:
- noaudio = noaudio + 1
- if modified > 0:
- deck.s.flush()
- deck.setModified()
- log.append('Total of %d cards, %d cards modified, no audio for %d cards, %d cards skipped.' % (total, modified, noaudio, total - modified))
- def doFill():
- """
- Update deck and display log information.
- """
- # Check if we have a deck open
- if mw.deck is None: return
- log = []
- log.append('Starting update.')
- process_deck(mw.deck, log)
- log.append('Update complete.')
- utils.showInfo('\n'.join(log))
- def init_hook():
- """
- Initialises the Anki GUI to present an option to invoke the plugin.
- """
- l.append(('Fill audio fields', FillAudioField))
- def init():
- mw.mainWin.toolBar.addSeparator()
- FillAudioField= QAction(mw)
- FillAudioField.setText(u"Fill Audio Field")
- FillAudioField.setEnabled(True)
- mw.connect(FillAudioField,SIGNAL("triggered()"),doFill)
- mw.mainWin.toolBar.addAction(FillAudioField)
- mw.addHook("init", init)
- mw.registerPlugin(u"Fill Audio Field", 666)
RAW Paste Data
