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:
parent
b03414a8d3
commit
06dff21107
@ -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
|
||||
|
@ -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('&', '&').replace('<', '<').replace('>', '>')
|
||||
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()
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user