Add support for video and pictures when adding or updating a note. (#207)

- Sound and video share same [sound:..] tag. See 0c08ff5317/pylib/anki/sound.py (L33)
- Tested and verified picture is added and video is added when `addNote` API.
This commit is contained in:
grepmew 2020-12-05 21:24:50 -08:00 committed by GitHub
parent b03414a8d3
commit 06dff21107
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 21 deletions

View File

@ -5,11 +5,11 @@
Creates a note using the given deck and model, with the provided field values and tags. Returns the identifier of
the created note created on success, and `null` on failure.
AnkiConnect can download audio files and embed them in newly created notes. The corresponding `audio` note member is
optional and can be omitted. If you choose to include it, it should contain a single object or an array of objects
AnkiConnect can download audio, video, and picture files and embed them in newly created notes. The corresponding `audio`, `video`, and `picture` note members are
optional and can be omitted. If you choose to include any of them, they should contain a single object or an array of objects
with mandatory `url` and `filename` fields. The `skipHash` field can be optionally provided to skip the inclusion of
downloaded files with an MD5 hash that matches the provided value. This is useful for avoiding the saving of error
pages and stub files. The `fields` member is a list of fields that should play audio when the card is displayed in
pages and stub files. The `fields` member is a list of fields that should play audio or video, or show a picture when the card is displayed in
Anki. The `allowDuplicate` member inside `options` group can be set to true to enable adding duplicate cards.
Normally duplicate cards can not be added and trigger exception.
@ -51,6 +51,22 @@
"fields": [
"Front"
]
}],
"video": [{
"url": "https://cdn.videvo.net/videvo_files/video/free/2015-06/small_watermarked/Contador_Glam_preview.mp4",
"filename": "countdown.mp4",
"skipHash": "4117e8aab0d37534d9c8eac362388bbe",
"fields": [
"Back"
]
}],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/A_black_cat_named_Tilly.jpg/220px-A_black_cat_named_Tilly.jpg",
"filename": "black_cat.jpg",
"skipHash": "8d6e4646dfae812bf39651b59d7429ce",
"fields": [
"Back"
]
}]
}
}
@ -95,6 +111,22 @@
"fields": [
"Front"
]
}],
"video": [{
"url": "https://cdn.videvo.net/videvo_files/video/free/2015-06/small_watermarked/Contador_Glam_preview.mp4",
"filename": "countdown.mp4",
"skipHash": "4117e8aab0d37534d9c8eac362388bbe",
"fields": [
"Back"
]
}],
"picture": [{
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/A_black_cat_named_Tilly.jpg/220px-A_black_cat_named_Tilly.jpg",
"filename": "black_cat.jpg",
"skipHash": "8d6e4646dfae812bf39651b59d7429ce",
"fields": [
"Back"
]
}]
}
]
@ -148,8 +180,8 @@
* **updateNoteFields**
Modify the fields of an exist note. You can also include audio files which will be added to the note with an
optional `audio` property. Please see the documentation for `addNote` for an explanation of objects in the `audio` array.
Modify the fields of an exist note. You can also include audio, video, or picture files which will be added to the note with an
optional `audio`, `video`, or `picture` property. Please see the documentation for `addNote` for an explanation of objects in the `audio`, `video`, or `picture` array.
*Sample request*:
```json

View File

@ -509,7 +509,13 @@ class AnkiConnect:
ankiNote = self.createNote(note)
audioObjectOrList = note.get('audio')
self.addAudio(ankiNote, audioObjectOrList)
self.addMedia(ankiNote, audioObjectOrList, util.MediaType.Audio)
videoObjectOrList = note.get('video')
self.addMedia(ankiNote, videoObjectOrList, util.MediaType.Video)
pictureObjectOrList = note.get('picture')
self.addMedia(ankiNote, pictureObjectOrList, util.MediaType.Picture)
collection = self.collection()
self.startEditing()
@ -522,20 +528,20 @@ class AnkiConnect:
return ankiNote.id
def addAudio(self, ankiNote, audioObjectOrList):
if audioObjectOrList is None:
def addMedia(self, ankiNote, mediaObjectOrList, mediaType):
if mediaObjectOrList is None:
return
if isinstance(audioObjectOrList, list):
audioList = audioObjectOrList
if isinstance(mediaObjectOrList, list):
mediaList = mediaObjectOrList
else:
audioList = [audioObjectOrList]
mediaList = [mediaObjectOrList]
for audio in audioList:
if audio is not None and len(audio['fields']) > 0:
for media in mediaList:
if media is not None and len(media['fields']) > 0:
try:
data = util.download(audio['url'])
skipHash = audio.get('skipHash')
data = util.download(media['url'])
skipHash = media.get('skipHash')
if skipHash is None:
skip = False
else:
@ -544,14 +550,17 @@ class AnkiConnect:
skip = skipHash == m.hexdigest()
if not skip:
audioFilename = self.media().writeData(audio['filename'], data)
for field in audio['fields']:
mediaFilename = self.media().writeData(media['filename'], data)
for field in media['fields']:
if field in ankiNote:
ankiNote[field] += u'[sound:{}]'.format(audioFilename)
if mediaType is util.MediaType.Picture:
ankiNote[field] += u'<div><img src="{}"><br></div>'.format(mediaFilename)
elif mediaType is util.MediaType.Audio or mediaType is util.MediaType.Video:
ankiNote[field] += u'[sound:{}]'.format(mediaFilename)
except Exception as e:
errorMessage = str(e).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
for field in audio['fields']:
for field in media['fields']:
if field in ankiNote:
ankiNote[field] += errorMessage
@ -575,7 +584,13 @@ class AnkiConnect:
ankiNote[name] = value
audioObjectOrList = note.get('audio')
self.addAudio(ankiNote, audioObjectOrList)
self.addMedia(ankiNote, audioObjectOrList, util.MediaType.Audio)
videoObjectOrList = note.get('video')
self.addMedia(ankiNote, videoObjectOrList, util.MediaType.Video)
pictureObjectOrList = note.get('picture')
self.addMedia(ankiNote, pictureObjectOrList, util.MediaType.Picture)
ankiNote.flush()

View File

@ -18,12 +18,17 @@ import os
import anki
import anki.sync
import aqt
import enum
#
# Utilities
#
class MediaType (enum.Enum):
Audio = 1
Video = 2
Picture = 3
def download(url):
client = anki.sync.AnkiRequestsClient()
client.timeout = setting('webTimeout') / 1000