|
import base64 |
|
import json |
|
import zipfile |
|
from io import BytesIO |
|
from pathlib import Path |
|
from typing import List |
|
|
|
from fastapi import HTTPException |
|
|
|
from voicevox_engine.model import DownloadableLibrary |
|
|
|
__all__ = ["LibraryManager"] |
|
|
|
INFO_FILE = "metas.json" |
|
|
|
|
|
class LibraryManager: |
|
def __init__(self, library_root_dir: Path): |
|
self.library_root_dir = library_root_dir |
|
self.library_root_dir.mkdir(exist_ok=True) |
|
|
|
def downloadable_libraries(self): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with open( |
|
"./engine_manifest_assets/downloadable_libraries.json", |
|
encoding="utf-8", |
|
) as f: |
|
libraries = json.load(f) |
|
speaker_info = libraries[0]["speakers"][0]["speaker_info"] |
|
mock_root_dir = Path("./speaker_info/7ffcb7ce-00ec-4bdc-82cd-45a8889e43ff") |
|
speaker_info["policy"] = (mock_root_dir / "policy.md").read_text() |
|
speaker_info["portrait"] = base64.b64encode( |
|
(mock_root_dir / "portrait.png").read_bytes() |
|
) |
|
for style_info in speaker_info["style_infos"]: |
|
style_id = style_info["id"] |
|
style_info["icon"] = base64.b64encode( |
|
(mock_root_dir / "icons" / f"{style_id}.png").read_bytes() |
|
) |
|
style_info["voice_samples"] = [ |
|
base64.b64encode( |
|
( |
|
mock_root_dir / "voice_samples" / f"{style_id}_{i:0>3}.wav" |
|
).read_bytes() |
|
) |
|
for i in range(1, 4) |
|
] |
|
return list(map(DownloadableLibrary.parse_obj, libraries)) |
|
|
|
def installed_libraries(self) -> List[DownloadableLibrary]: |
|
library = [] |
|
for library_dir in self.library_root_dir.iterdir(): |
|
if library_dir.is_dir(): |
|
with open(library_dir / INFO_FILE, encoding="utf-8") as f: |
|
library.append(json.load(f)) |
|
return library |
|
|
|
def install_library(self, library_id: str, file: BytesIO): |
|
for downloadable_library in self.downloadable_libraries(): |
|
if downloadable_library.uuid == library_id: |
|
library_info = downloadable_library.dict() |
|
break |
|
else: |
|
raise HTTPException(status_code=404, detail="指定された音声ライブラリが見つかりません。") |
|
library_dir = self.library_root_dir / library_id |
|
library_dir.mkdir(exist_ok=True) |
|
with open(library_dir / INFO_FILE, "w", encoding="utf-8") as f: |
|
json.dump(library_info, f, indent=4, ensure_ascii=False) |
|
with zipfile.ZipFile(file) as zf: |
|
if zf.testzip() is not None: |
|
raise HTTPException(status_code=422, detail="不正なZIPファイルです。") |
|
|
|
zf.extractall(library_dir) |
|
return library_dir |
|
|