Skip to content

Commit

Permalink
🎨 refactor(generate_voice): update speaker attributes and API usage
Browse files Browse the repository at this point in the history
- Renamed 'sid' to 'voice' and updated default seed in `Speaker`
- Updated `VoiceSpeakerV1` enum to use 'voice' attribute
- Changed `voice_engine` to `speaker` in `build` method
- Adjusted API request method from `get` to `post`
- Added support for additional audio content types in response handling

🔖 chore: bump version to 0.7.3 in pyproject.toml
  • Loading branch information
sudoskys committed Jan 4, 2025
1 parent 5beb504 commit 1b2d0bc
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 45 deletions.
2 changes: 1 addition & 1 deletion playground/generate_voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async def generate_voice(text: str):
try:
voice_gen = VoiceGenerate.build(
text=text,
voice_engine=VoiceSpeakerV1.Crina, # VoiceSpeakerV2.Ligeia,
speaker=VoiceSpeakerV2.Ligeia, # VoiceSpeakerV2.Ligeia,
)
result = await voice_gen.request(
session=credential
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "novelai-python"
version = "0.7.2"
version = "0.7.3"
description = "NovelAI Python Binding With Pydantic"
authors = [
{ name = "sudoskys", email = "[email protected]" },
Expand Down
50 changes: 22 additions & 28 deletions src/novelai_python/sdk/ai/generate_voice/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# @Author : sudoskys
from enum import Enum
from typing import Optional, Union, Literal
from urllib.parse import urlparse

Expand All @@ -11,7 +12,7 @@
from pydantic import ConfigDict, PrivateAttr, Field, model_validator
from tenacity import wait_random, retry, stop_after_attempt, retry_if_exception

from ._enum import VoiceSpeakerV1, VoiceSpeakerV2
from ._enum import VoiceSpeakerV1, VoiceSpeakerV2, Speaker
from ...schema import ApiBaseModel
from ...._exceptions import APIError, SessionHttpError
from ...._response.ai.generate_voice import VoiceResponse
Expand Down Expand Up @@ -80,43 +81,36 @@ async def necessary_headers(self, request_data) -> dict:
@classmethod
def build(cls,
text: str,
voice_engine: Union[VoiceSpeakerV1, VoiceSpeakerV2, str],
speaker: Union[VoiceSpeakerV2, VoiceSpeakerV1, Speaker, str],
*,
opus: bool = False
opus: bool = True
) -> "VoiceGenerate":
"""
生成图片
:param opus: unknown
:param text: str
:param voice_engine: VoiceSpeakerV1 or VoiceSpeakerV2 or str
:param speaker: Speaker import from novelai_python.sdk.ai.generate_voice._enum
:return: VoiceGenerate instance
:raises: ValueError
"""
if isinstance(voice_engine, str):
if isinstance(speaker, Enum):
speaker = speaker.value

if isinstance(speaker, str):
return cls(
text=text,
voice=-1,
seed=voice_engine,
opus=opus,
version="v2"
)
if isinstance(voice_engine, VoiceSpeakerV2):
return cls(
text=text,
seed=voice_engine.value.seed,
voice=voice_engine.value.sid,
seed=speaker,
opus=opus,
version="v2"
)
if isinstance(voice_engine, VoiceSpeakerV1):
return cls(
text=text,
seed=voice_engine.value.seed,
voice=voice_engine.value.sid,
opus=opus,
version="v1"
)
raise ValueError("Invalid voice engine")
return cls(
text=text,
seed=speaker.seed,
voice=speaker.voice,
opus=opus,
version=speaker.version
)

@retry(
wait=wait_random(min=1, max=3),
Expand Down Expand Up @@ -147,13 +141,13 @@ async def request(self,
logger.debug(f"Voice request data: {request_data}")
# Request
try:
assert hasattr(sess, "get"), "session must have get method."
response = await sess.get(
self.base_url,
params=request_data
assert hasattr(sess, "post"), "session must have get method."
response = await sess.post(
url=self.base_url,
json=request_data
)
header_type = response.headers.get('Content-Type')
if header_type not in ['audio/mpeg', 'audio/ogg', 'audio/opus']:
if header_type not in ['audio/mpeg', 'audio/ogg', 'audio/opus', 'audio/wav', 'audio/webm']:
logger.warning(
f"Error with content type: {header_type} and code: {response.status_code}"
)
Expand Down
29 changes: 14 additions & 15 deletions src/novelai_python/sdk/ai/generate_voice/_enum.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
from typing import Optional
from enum import Enum

from pydantic import BaseModel
from enum import Enum


class Speaker(BaseModel):
"""
Speaker for /ai/generated_voice
"""
sid: int = -1
seed: Optional[str] = None
voice: int = -1
seed: str = "kurumuz12"
name: str
category: str

@property
def version(self):
return "v2" if self.sid is None else "v1"
return "v2" if self.voice == -1 else "v1"


class VoiceSpeakerV1(Enum):
"""
Speaker for /ai/generated_voice
"""
Cyllene = Speaker(sid=17, name="Cyllene", category="female")
Leucosia = Speaker(sid=95, name="Leucosia", category="female")
Crina = Speaker(sid=44, name="Crina", category="female")
Hespe = Speaker(sid=80, name="Hespe", category="female")
Ida = Speaker(sid=106, name="Ida", category="female")
Alseid = Speaker(sid=6, name="Alseid", category="male")
Daphnis = Speaker(sid=10, name="Daphnis", category="male")
Echo = Speaker(sid=16, name="Echo", category="male")
Thel = Speaker(sid=41, name="Thel", category="male")
Nomios = Speaker(sid=77, name="Nomios", category="male")
Cyllene = Speaker(voice=17, name="Cyllene", category="female")
Leucosia = Speaker(voice=95, name="Leucosia", category="female")
Crina = Speaker(voice=44, name="Crina", category="female")
Hespe = Speaker(voice=80, name="Hespe", category="female")
Ida = Speaker(voice=106, name="Ida", category="female")
Alseid = Speaker(voice=6, name="Alseid", category="male")
Daphnis = Speaker(voice=10, name="Daphnis", category="male")
Echo = Speaker(voice=16, name="Echo", category="male")
Thel = Speaker(voice=41, name="Thel", category="male")
Nomios = Speaker(voice=77, name="Nomios", category="male")
# SeedInput = Speaker(sid=-1, name="Seed Input", category="custom")


Expand Down

0 comments on commit 1b2d0bc

Please sign in to comment.