-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to import media file from memory instead of from hdd? #102
Comments
Easy. Just import genanki then create a new package class that inherits from genanki's package class. Then simply override the requisite write_to_file function to a custom one that writes media files from either memory or db or whatever by switching out the outzip.write to a outzip.writestr with a bytes array of the media data you want to write. |
Here is something off the cuff totally untested but should give you something to start with: from genanki import package
from typing import Optional
import zipfile
from copy import deepcopy
import os
import json
class Package(package.Package):
def __init__(self, deck_or_decks=None, media_files=None, media_function=None):
super().__init__(deck_or_decks, media_files)
self.media_function = media_function
def write_to_file(self, file, timestamp: Optional[float] = None):
if callable(self.media_function):
media_files = deepcopy(self.media_files)
self.media_files = []
ret = super().write_to_file(file, timestamp)
self.media_files = media_files
with zipfile.ZipFile(file, 'a') as outzip:
media_file_idx_to_path = dict(enumerate(self.media_files))
media_json = {idx: os.path.basename(path) for idx, path in media_file_idx_to_path.items()}
outzip.writestr('media', json.dumps(media_json))
for idx, path in media_file_idx_to_path.items():
self.media_function(outzip, path, idx)
return ret
else:
return super().write_to_file(file, timestamp) |
Thank you very much for your help. I will try it. |
…ctionality more easily
…rride write functionality
…rride write functionality
…rride write functionality
Hey, so don't use what I previously wrote. it will leave duplicate media files (not sure if this can cause errors, but just to be safe here is alternative). Use this instead the following. When tested on my own decks it worked fine. Also below that is an example of a media_function that I used to get values from db. Notice how genanki only really needs idx and data for said idx, while path really can be whatever you want it to be in collection.media anki folder. Hence use path to be unique identifier for you to identify the correct asset to write in media function. from genanki import package
from typing import Optional
import zipfile
from copy import deepcopy
import os
import json
class Package(package.Package):
def __init__(self, deck_or_decks=None, media_files=None, media_function=None):
super().__init__(deck_or_decks, media_files)
self.media_function = media_function
def write_to_file(self, file, timestamp: Optional[float] = None):
with tempfile.NamedTemporaryFile() as dbfilename:
with sqlite3.connect(dbfilename.name) as conn:
cursor = conn.cursor()
if timestamp is None: timestamp = time.time()
id_gen = itertools.count(int(timestamp * 1000))
self.write_to_db(cursor, timestamp, id_gen)
with tempfile.NamedTemporaryFile(dir=os.path.dirname(file), suffix='.apkg', delete=False) as tempapkg:
with zipfile.ZipFile(tempapkg.name, 'w') as outzip:
outzip.write(dbfilename.name, 'collection.anki2')
media_file_idx_to_path = dict(enumerate(self.media_files))
media_json = {idx: os.path.basename(path) for idx, path in media_file_idx_to_path.items()}
outzip.writestr('media', json.dumps(media_json))
for idx, path in media_file_idx_to_path.items():
if callable(self.media_function):
self.media_function(outzip, idx, path)
else:
outzip.write(path, str(idx))
try:
shutil.move(tempapkg.name, file)
except Exception as e:
tempapkg.close()
raise e def media_function(outzip, idx, path):
hash_id, table = media_files[path]
data = con.execute(f'select data from {table} where hash_id = ?', (hash_id,)).fetchone()[0]
outzip.writestr(str(idx), data) |
Hello, is there a way how to insert media file from memory instead of hdd? I want copy every image to the memory and then insert it to the card. Now i’m importing many images to the cards, the problem is that i must rename every image before i can insert it to the card. Or is there another better way? I know i can create renamed copy of every image but it would unnecessarily strains the hdd.
The text was updated successfully, but these errors were encountered: