Page MenuHomePhabricator

Anki Plugin for Lingua Libre
Closed, ResolvedPublicFeature

Description

The overall goal of the Anki plugin for Lingua Libre should be to enable users to rapidly add audio from Lingua Libre to their flashcards. The challenge lies in the highly variable way that users add their flash cards. This requires a highly flexible configuration and processing. We also don't want users to download an entire dump if they only want to add ten files.

Configuration in Json:

There should be one configuration for each deck in case users have multiple language with varying layouts.

Deck_Name {
    Language = “Iso_3_Code” – let’s the program know which language the audio should be in
    Accent = “Accent” - Determines which accent the user wants. Requires the implementation of standard accent metadata on LL. 
    Fields = {“Query_1”, Audio_1”;… “Query_N”, “Audio_N”} – Each Pair Contains the Query Field that contains the string to look up and the Audio Field where the audio file(s) should be placed.
    Filename = "" allows users to set a custom filename for audio downloaded from Lingua Libre. The default should be {{language}}_{{accent}}_{{speaker}}_{{word}}
    Filetype = "" allows users to decide which file format they prefer, could be wav, mp3, or flac. It should not be ogg because iOS does not support ogg.
    Prefixes = {“Prefix_1”; …; “Prefix_N”} Removes the text only from the beginning of the Query string. Useful for dealing with articles, pronouns, etc.
    Remove = {“”; …; “”} Contains a list of characters to remove from the text string in the Query Field.
    Replace = {“Find_1”, “Replace_1”; …; “Find_N”, “Replace_N”} Enables simple find and replace operations. Useful for dealing with special characters such replacing … with … 
    Separator = “Character” – Allows the division of the text in the Query Field into multiple queries. For example, if Separator = “,” Query_1 “oisif, oisive” will become Query_1A “oisif” and Query_1B  “oisive”
    Audio_Separator = “Character” – Selects the character used to separate the audio files if Separator is non-blank, e.g. “,” or “;”
    Ignore_Speakers = {“User_1”, …, “User_N”} – Never add audio from any of these speakers.
    Prefer_Speakers = {“User_1”, …. “User_N”} – Ranked List of the pronouncers that the user prefers. 
    Tag_Missing = Yes/No/Only_Separator – Choose whether to tag the cards for which the query does not return a result. If “Yes”, all cards that are missing audio for the Query or one of the sub-Queries, if the Separator is enabled. If “No”, never tag the missing audio. If “Only_Separator”, only tag cards for which one of more of the sub_queries is missing.
    Tag_Text = “” – Allow user to set the tag for the Tag_Missing option 
    Recheck_Missing = “” – Set the number of days before rechecking cards with "Tag_Text". If all the queries for the card succeed, then the Tag_Text should be removed.
}

Order of Operations for Textual Manipulation

  1. First split the Query Field according to “Separator”
  2. Second, perform Prefixes operation
  3. Third, perform “Remove” operation
  4. Fourth, perform “Replace” operation

Crude Flow Chart for Batch Processing:
Batch processing is important when users have multiple cards to update. Nobody wants to manually download 20,000 files.

  1. User Invokes Lingua Libre Plugin by going to Tools - > Lingua Libre
  2. Dialog Prompts User to Select Deck or Subdeck.
  3. Lingua Libre check if configuration exists for the Deck or Subdeck. If Yes -> Proceed; If No -> “No Configuration for {{Deck}} exists.
  4. Lingua Libre checks if the Query Field and Audio Field in the Configuration exist for the {{Deck}}. If Query_Field does not exist -> “Error {{Query_Field}} does not exist”; If Audio_Field does not exist -> “Error {{Audio_Field}} does not exist; Otherwise, proceed
  5. Create an array with Note_ID; Text from Query_Field; Audio_Field . When getting the text from the Query_Field, all HTML should be stripped. If there are multiple Query/Audio pairs in the configuration, each Note_ID will have multiple entries.
  6. Perform Textual Manipulation, based on the Order of Operations, rebuild array
  7. For each entry in the array, check Query on Libre Lingua, download file if exists into the Anki Media Folder File, empty Audio_Field, paste [sound:File] into the Audio Field
    1. Note if the separator is enabled, then multiple queries will need to be performed and the results stored until they can be linked together. For example, for “oisif, oisive”, the program will first need to check for “oisif” download the file; remember the filename. Then, check for “oisive”, download the file; remember the filename. Once all the subqueries for the card are complete, the audio_file references will need to be passed in as [file:“Audio_1”]“Audio_Separator”[sound: “Audio_2”]
    2. Note 2: The Batch download should use the Ignore_Speaker and Prefer_Speaker options to perform automatic filtering.
  8. While the program is checking the Queries. There Should be a dialog box. Title “Checking on Lingua Libre” Message Checking for “Query” /n “X Notes and Y Queries” remaining.; Estimated Time: XX:XX:XX; Display Progress Bar with Percentage based on Queries_Finished/Total_Queries
    1. Note: X Notes and Y Queries are necessary if there are multiple Query/Audio Fields or if the separator is enabled.
  9. Upon Finishing, Display “X Number of Notes Updates. Z out of Y Queries were Successful.”

Adding Audio for single note
It’s useful to also add a button in the toolbar to enable adding audio to just one note.

  1. User presses on Lingua Libre logo on the Toolbar.
  2. The script automatically fetches the Deck or Sub_Deck information.
  3. Perform Steps 3 – 6 from the Batch Process
  4. Download all results for each Query and perform automatic filtering based on the Ignore_Speaker and Prefer_Speaker options
  5. Display Dialog_Box. Title: Found Audio. Main Dialog Text: “There are the following pronunciations for “Query” on Libre Libre.” Selection Box with the User_Names. Navigate using the up-and-down key. Enter adds the file. Also, have “Cancel” and “Add” buttons on the bottom.
  6. This button would also need to handle multiple Query/Audio fields and splitting of a single Query list. Basically, go through the array and repeat Step 5.

Related Objects

Event Timeline

Yug updated the task description. (Show Details)
Yug subscribed.
Pamputt changed the subtype of this task from "Task" to "Feature Request".Dec 11 2020, 10:00 PM

I've begun working on this and I've written the Anki part in python and tested it by downloading audio from Forvo. The code is available on github. I'm trying to reuse the code from the LinguaLibre bot, but I'm having trouble writing the sparql function. I would like to send a query to LingaLibre containing a term and language that would return all the available pronunciations performed by native speakers, the user name of the speaker, and their learning place [or whatever works as the best proxy for accent]. Can anyone help with writing this query function?

For example, a query for ubiquiste with the language code "fra" would return
LL-Q150 (fra)-Pamputt-ubiquiste.wav
LL-Q150 (fra)-Lyokoï-ubiquiste.wav
LL-Q150 (fra)-VictorDtmtc-ubiquiste.wav

My own ideas is that it should work something like this

def fetch_LL_audio(term, language, learning_place):
       if not learning_place:
              query = term + language
       else:
               query = term + language + learning_place
     
       records = get_records(query)
       
        for i in Records:
            download_audio(Records['file'])

Also, is there a way to download the mp3 files directly instead of the wav files?

Ok, I semi-figured it out.

For the language, you use
filters += 'OPTIONAL { ?language prop:P13 ?languageIso.} FILTER( ?languageIso = "' + iso + '" ).'

and for the term, you use
filters += '?record prop:P7 ?transcription. FILTER( ?transcription = "' + term + '" ).'

Is there a way to speed up the query because it appears to be quite slow.

I assume for downloading, you scrape the commons page and then find<source src="file" type="audio/mpeg" data-title="MP3" data-shorttitle="MP3" data-transcodekey="mp3" data-width="0" data-height="0" data-bandwidth=""/>

Also, am I correct that you need to query wikidata to transform the speaker_residence into human understandable?