| | import warnings |
| | from enum import Enum |
| | from typing import Any, List, Optional, Union |
| |
|
| | import pydantic |
| | from pydantic import BaseModel |
| |
|
| | |
| | warnings.filterwarnings( |
| | "ignore", |
| | category=UserWarning, |
| | message="Field name.*shadows an attribute in parent.*", |
| | ) |
| |
|
| |
|
| | class VideoConcatMode(str, Enum): |
| | random = "random" |
| | sequential = "sequential" |
| |
|
| |
|
| | class VideoTransitionMode(str, Enum): |
| | none = None |
| | shuffle = "Shuffle" |
| | fade_in = "FadeIn" |
| | fade_out = "FadeOut" |
| | slide_in = "SlideIn" |
| | slide_out = "SlideOut" |
| |
|
| |
|
| | class VideoAspect(str, Enum): |
| | landscape = "16:9" |
| | portrait = "9:16" |
| | square = "1:1" |
| |
|
| | def to_resolution(self): |
| | if self == VideoAspect.landscape.value: |
| | return 1920, 1080 |
| | elif self == VideoAspect.portrait.value: |
| | return 1080, 1920 |
| | elif self == VideoAspect.square.value: |
| | return 1080, 1080 |
| | return 1080, 1920 |
| |
|
| |
|
| | class _Config: |
| | arbitrary_types_allowed = True |
| |
|
| |
|
| | @pydantic.dataclasses.dataclass(config=_Config) |
| | class MaterialInfo: |
| | provider: str = "pexels" |
| | url: str = "" |
| | duration: int = 0 |
| |
|
| |
|
| | class VideoParams(BaseModel): |
| | """ |
| | { |
| | "video_subject": "", |
| | "video_aspect": "横屏 16:9(西瓜视频)", |
| | "voice_name": "女生-晓晓", |
| | "bgm_name": "random", |
| | "font_name": "STHeitiMedium 黑体-中", |
| | "text_color": "#FFFFFF", |
| | "font_size": 60, |
| | "stroke_color": "#000000", |
| | "stroke_width": 1.5 |
| | } |
| | """ |
| |
|
| | video_subject: str |
| | video_script: str = "" |
| | video_terms: Optional[str | list] = None |
| | video_aspect: Optional[VideoAspect] = VideoAspect.portrait.value |
| | video_concat_mode: Optional[VideoConcatMode] = VideoConcatMode.random.value |
| | video_transition_mode: Optional[VideoTransitionMode] = None |
| | video_clip_duration: Optional[int] = 5 |
| | video_count: Optional[int] = 1 |
| |
|
| | video_source: Optional[str] = "pexels" |
| | video_materials: Optional[List[MaterialInfo]] = ( |
| | None |
| | ) |
| |
|
| | video_language: Optional[str] = "" |
| |
|
| | voice_name: Optional[str] = "" |
| | voice_volume: Optional[float] = 1.0 |
| | voice_rate: Optional[float] = 1.0 |
| | bgm_type: Optional[str] = "random" |
| | bgm_file: Optional[str] = "" |
| | bgm_volume: Optional[float] = 0.2 |
| |
|
| | subtitle_enabled: Optional[bool] = True |
| | subtitle_position: Optional[str] = "bottom" |
| | custom_position: float = 70.0 |
| | font_name: Optional[str] = "STHeitiMedium.ttc" |
| | text_fore_color: Optional[str] = "#FFFFFF" |
| | text_background_color: Union[bool, str] = True |
| |
|
| | font_size: int = 60 |
| | stroke_color: Optional[str] = "#000000" |
| | stroke_width: float = 1.5 |
| | n_threads: Optional[int] = 2 |
| | paragraph_number: Optional[int] = 1 |
| |
|
| |
|
| | class SubtitleRequest(BaseModel): |
| | video_script: str |
| | video_language: Optional[str] = "" |
| | voice_name: Optional[str] = "zh-CN-XiaoxiaoNeural-Female" |
| | voice_volume: Optional[float] = 1.0 |
| | voice_rate: Optional[float] = 1.2 |
| | bgm_type: Optional[str] = "random" |
| | bgm_file: Optional[str] = "" |
| | bgm_volume: Optional[float] = 0.2 |
| | subtitle_position: Optional[str] = "bottom" |
| | font_name: Optional[str] = "STHeitiMedium.ttc" |
| | text_fore_color: Optional[str] = "#FFFFFF" |
| | text_background_color: Union[bool, str] = True |
| | font_size: int = 60 |
| | stroke_color: Optional[str] = "#000000" |
| | stroke_width: float = 1.5 |
| | video_source: Optional[str] = "local" |
| | subtitle_enabled: Optional[str] = "true" |
| |
|
| |
|
| | class AudioRequest(BaseModel): |
| | video_script: str |
| | video_language: Optional[str] = "" |
| | voice_name: Optional[str] = "zh-CN-XiaoxiaoNeural-Female" |
| | voice_volume: Optional[float] = 1.0 |
| | voice_rate: Optional[float] = 1.2 |
| | bgm_type: Optional[str] = "random" |
| | bgm_file: Optional[str] = "" |
| | bgm_volume: Optional[float] = 0.2 |
| | video_source: Optional[str] = "local" |
| |
|
| |
|
| | class VideoScriptParams: |
| | """ |
| | { |
| | "video_subject": "春天的花海", |
| | "video_language": "", |
| | "paragraph_number": 1 |
| | } |
| | """ |
| |
|
| | video_subject: Optional[str] = "春天的花海" |
| | video_language: Optional[str] = "" |
| | paragraph_number: Optional[int] = 1 |
| |
|
| |
|
| | class VideoTermsParams: |
| | """ |
| | { |
| | "video_subject": "", |
| | "video_script": "", |
| | "amount": 5 |
| | } |
| | """ |
| |
|
| | video_subject: Optional[str] = "春天的花海" |
| | video_script: Optional[str] = ( |
| | "春天的花海,如诗如画般展现在眼前。万物复苏的季节里,大地披上了一袭绚丽多彩的盛装。金黄的迎春、粉嫩的樱花、洁白的梨花、艳丽的郁金香……" |
| | ) |
| | amount: Optional[int] = 5 |
| |
|
| |
|
| | class BaseResponse(BaseModel): |
| | status: int = 200 |
| | message: Optional[str] = "success" |
| | data: Any = None |
| |
|
| |
|
| | class TaskVideoRequest(VideoParams, BaseModel): |
| | pass |
| |
|
| |
|
| | class TaskQueryRequest(BaseModel): |
| | pass |
| |
|
| |
|
| | class VideoScriptRequest(VideoScriptParams, BaseModel): |
| | pass |
| |
|
| |
|
| | class VideoTermsRequest(VideoTermsParams, BaseModel): |
| | pass |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | class TaskResponse(BaseResponse): |
| | class TaskResponseData(BaseModel): |
| | task_id: str |
| |
|
| | data: TaskResponseData |
| |
|
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": {"task_id": "6c85c8cc-a77a-42b9-bc30-947815aa0558"}, |
| | }, |
| | } |
| |
|
| |
|
| | class TaskQueryResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": { |
| | "state": 1, |
| | "progress": 100, |
| | "videos": [ |
| | "http://127.0.0.1:8080/tasks/6c85c8cc-a77a-42b9-bc30-947815aa0558/final-1.mp4" |
| | ], |
| | "combined_videos": [ |
| | "http://127.0.0.1:8080/tasks/6c85c8cc-a77a-42b9-bc30-947815aa0558/combined-1.mp4" |
| | ], |
| | }, |
| | }, |
| | } |
| |
|
| |
|
| | class TaskDeletionResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": { |
| | "state": 1, |
| | "progress": 100, |
| | "videos": [ |
| | "http://127.0.0.1:8080/tasks/6c85c8cc-a77a-42b9-bc30-947815aa0558/final-1.mp4" |
| | ], |
| | "combined_videos": [ |
| | "http://127.0.0.1:8080/tasks/6c85c8cc-a77a-42b9-bc30-947815aa0558/combined-1.mp4" |
| | ], |
| | }, |
| | }, |
| | } |
| |
|
| |
|
| | class VideoScriptResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": { |
| | "video_script": "春天的花海,是大自然的一幅美丽画卷。在这个季节里,大地复苏,万物生长,花朵争相绽放,形成了一片五彩斑斓的花海..." |
| | }, |
| | }, |
| | } |
| |
|
| |
|
| | class VideoTermsResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": {"video_terms": ["sky", "tree"]}, |
| | }, |
| | } |
| |
|
| |
|
| | class BgmRetrieveResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": { |
| | "files": [ |
| | { |
| | "name": "output013.mp3", |
| | "size": 1891269, |
| | "file": "/MoneyPrinterTurbo/resource/songs/output013.mp3", |
| | } |
| | ] |
| | }, |
| | }, |
| | } |
| |
|
| |
|
| | class BgmUploadResponse(BaseResponse): |
| | class Config: |
| | json_schema_extra = { |
| | "example": { |
| | "status": 200, |
| | "message": "success", |
| | "data": {"file": "/MoneyPrinterTurbo/resource/songs/example.mp3"}, |
| | }, |
| | } |
| |
|