local-coze 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- local_coze/__init__.py +110 -0
- local_coze/cli/__init__.py +3 -0
- local_coze/cli/chat.py +126 -0
- local_coze/cli/cli.py +34 -0
- local_coze/cli/constants.py +7 -0
- local_coze/cli/db.py +81 -0
- local_coze/cli/embedding.py +193 -0
- local_coze/cli/image.py +162 -0
- local_coze/cli/knowledge.py +195 -0
- local_coze/cli/search.py +198 -0
- local_coze/cli/utils.py +41 -0
- local_coze/cli/video.py +191 -0
- local_coze/cli/video_edit.py +888 -0
- local_coze/cli/voice.py +351 -0
- local_coze/core/__init__.py +25 -0
- local_coze/core/client.py +253 -0
- local_coze/core/config.py +58 -0
- local_coze/core/exceptions.py +67 -0
- local_coze/database/__init__.py +29 -0
- local_coze/database/client.py +170 -0
- local_coze/database/migration.py +342 -0
- local_coze/embedding/__init__.py +31 -0
- local_coze/embedding/client.py +350 -0
- local_coze/embedding/models.py +130 -0
- local_coze/image/__init__.py +19 -0
- local_coze/image/client.py +110 -0
- local_coze/image/models.py +163 -0
- local_coze/knowledge/__init__.py +19 -0
- local_coze/knowledge/client.py +148 -0
- local_coze/knowledge/models.py +45 -0
- local_coze/llm/__init__.py +25 -0
- local_coze/llm/client.py +317 -0
- local_coze/llm/models.py +48 -0
- local_coze/memory/__init__.py +14 -0
- local_coze/memory/client.py +176 -0
- local_coze/s3/__init__.py +12 -0
- local_coze/s3/client.py +580 -0
- local_coze/s3/models.py +18 -0
- local_coze/search/__init__.py +19 -0
- local_coze/search/client.py +183 -0
- local_coze/search/models.py +57 -0
- local_coze/video/__init__.py +17 -0
- local_coze/video/client.py +347 -0
- local_coze/video/models.py +39 -0
- local_coze/video_edit/__init__.py +23 -0
- local_coze/video_edit/examples.py +340 -0
- local_coze/video_edit/frame_extractor.py +176 -0
- local_coze/video_edit/models.py +362 -0
- local_coze/video_edit/video_edit.py +631 -0
- local_coze/voice/__init__.py +17 -0
- local_coze/voice/asr.py +82 -0
- local_coze/voice/models.py +86 -0
- local_coze/voice/tts.py +94 -0
- local_coze-0.0.1.dist-info/METADATA +636 -0
- local_coze-0.0.1.dist-info/RECORD +58 -0
- local_coze-0.0.1.dist-info/WHEEL +4 -0
- local_coze-0.0.1.dist-info/entry_points.txt +3 -0
- local_coze-0.0.1.dist-info/licenses/LICENSE +21 -0
local_coze/cli/video.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
from coze_coding_utils.runtime_ctx.context import new_context
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
8
|
+
from rich.table import Table
|
|
9
|
+
|
|
10
|
+
from ..core.config import Config
|
|
11
|
+
from ..core.exceptions import APIError
|
|
12
|
+
from ..video import (
|
|
13
|
+
ImageURL,
|
|
14
|
+
ImageURLContent,
|
|
15
|
+
TextContent,
|
|
16
|
+
VideoGenerationClient,
|
|
17
|
+
)
|
|
18
|
+
from .constants import RUN_MODE_HEADER, RUN_MODE_TEST
|
|
19
|
+
|
|
20
|
+
console = Console()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def parse_resolution(size: Optional[str]) -> tuple[Optional[str], Optional[str]]:
|
|
24
|
+
if not size:
|
|
25
|
+
return None, None
|
|
26
|
+
|
|
27
|
+
width, height = size.split("x")
|
|
28
|
+
w, h = int(width), int(height)
|
|
29
|
+
|
|
30
|
+
if w == h:
|
|
31
|
+
return "1:1", "720p" if w <= 1024 else "1080p"
|
|
32
|
+
elif w > h:
|
|
33
|
+
return "16:9", "720p" if w <= 1440 else "1080p"
|
|
34
|
+
else:
|
|
35
|
+
return "9:16", "720p" if h <= 1440 else "1080p"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@click.command()
|
|
39
|
+
@click.option("--prompt", "-p", help="文本提示词")
|
|
40
|
+
@click.option("--image-url", "-i", help="图片URL(单个或逗号分隔的两个)")
|
|
41
|
+
@click.option("--size", "-s", help="视频分辨率(如 1920x1080)")
|
|
42
|
+
@click.option("--duration", "-d", type=int, help="视频时长(5-10秒)")
|
|
43
|
+
@click.option("--model", "-m", help="模型名称")
|
|
44
|
+
@click.option("--callback-url", help="回调URL")
|
|
45
|
+
@click.option("--return-last-frame", is_flag=True, help="返回尾帧图像")
|
|
46
|
+
@click.option("--watermark", is_flag=True, default=False, help="添加水印")
|
|
47
|
+
@click.option("--seed", type=int, help="随机种子")
|
|
48
|
+
@click.option("--camerafixed", is_flag=True, help="固定摄像头")
|
|
49
|
+
@click.option("--output", "-o", type=click.Path(), help="输出文件路径(JSON)")
|
|
50
|
+
@click.option("--mock", is_flag=True, help="使用 mock 模式(测试运行)")
|
|
51
|
+
@click.option(
|
|
52
|
+
"--header",
|
|
53
|
+
"-H",
|
|
54
|
+
multiple=True,
|
|
55
|
+
help="自定义 HTTP 请求头 (格式: 'Key: Value' 或 'Key=Value',可多次使用)",
|
|
56
|
+
)
|
|
57
|
+
@click.option("--verbose", "-v", is_flag=True, help="显示详细的 HTTP 请求日志")
|
|
58
|
+
def video(
|
|
59
|
+
prompt: Optional[str],
|
|
60
|
+
image_url: Optional[str],
|
|
61
|
+
size: Optional[str],
|
|
62
|
+
duration: Optional[int],
|
|
63
|
+
model: Optional[str],
|
|
64
|
+
callback_url: Optional[str],
|
|
65
|
+
return_last_frame: bool,
|
|
66
|
+
watermark: bool,
|
|
67
|
+
seed: Optional[int],
|
|
68
|
+
camerafixed: bool,
|
|
69
|
+
output: Optional[str],
|
|
70
|
+
mock: bool,
|
|
71
|
+
header: tuple,
|
|
72
|
+
verbose: bool,
|
|
73
|
+
):
|
|
74
|
+
"""同步生成视频(等待完成)"""
|
|
75
|
+
try:
|
|
76
|
+
from .utils import parse_headers
|
|
77
|
+
|
|
78
|
+
config = Config()
|
|
79
|
+
|
|
80
|
+
ctx = None
|
|
81
|
+
custom_headers = parse_headers(header) or {}
|
|
82
|
+
|
|
83
|
+
if mock:
|
|
84
|
+
ctx = new_context(method="video.generate", headers=custom_headers)
|
|
85
|
+
custom_headers[RUN_MODE_HEADER] = RUN_MODE_TEST
|
|
86
|
+
console.print("[yellow]🧪 Mock 模式已启用(测试运行)[/yellow]")
|
|
87
|
+
|
|
88
|
+
client = VideoGenerationClient(
|
|
89
|
+
config, ctx=ctx, custom_headers=custom_headers, verbose=verbose
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
image_urls = None
|
|
93
|
+
if image_url:
|
|
94
|
+
image_urls = [url.strip() for url in image_url.split(",")]
|
|
95
|
+
|
|
96
|
+
ratio, resolution = parse_resolution(size)
|
|
97
|
+
|
|
98
|
+
content_items = []
|
|
99
|
+
|
|
100
|
+
if prompt:
|
|
101
|
+
content_items.append(TextContent(text=prompt))
|
|
102
|
+
|
|
103
|
+
if image_urls:
|
|
104
|
+
if len(image_urls) == 1:
|
|
105
|
+
content_items.append(
|
|
106
|
+
ImageURLContent(
|
|
107
|
+
image_url=ImageURL(url=image_urls[0]), role="first_frame"
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
elif len(image_urls) == 2:
|
|
111
|
+
content_items.append(
|
|
112
|
+
ImageURLContent(
|
|
113
|
+
image_url=ImageURL(url=image_urls[0]), role="first_frame"
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
content_items.append(
|
|
117
|
+
ImageURLContent(
|
|
118
|
+
image_url=ImageURL(url=image_urls[1]), role="last_frame"
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
else:
|
|
122
|
+
raise ValueError("Only 1 or 2 images are supported")
|
|
123
|
+
|
|
124
|
+
if not content_items:
|
|
125
|
+
raise ValueError("Either --prompt or --image-url must be provided")
|
|
126
|
+
|
|
127
|
+
model_name = model or "doubao-seedance-1-0-pro-fast-251015"
|
|
128
|
+
|
|
129
|
+
with Progress(
|
|
130
|
+
SpinnerColumn(),
|
|
131
|
+
TextColumn("[progress.description]{task.description}"),
|
|
132
|
+
console=console,
|
|
133
|
+
) as progress:
|
|
134
|
+
task = progress.add_task("[cyan]Generating video...", total=None)
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
video_url, response, last_frame_url = client.video_generation(
|
|
138
|
+
content_items=content_items,
|
|
139
|
+
model=model_name,
|
|
140
|
+
callback_url=callback_url,
|
|
141
|
+
return_last_frame=return_last_frame,
|
|
142
|
+
resolution=resolution or "720p",
|
|
143
|
+
ratio=ratio or "16:9",
|
|
144
|
+
duration=duration or 5,
|
|
145
|
+
watermark=watermark,
|
|
146
|
+
seed=seed,
|
|
147
|
+
camerafixed=camerafixed,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
progress.update(
|
|
151
|
+
task, description="[green]✓ Video generation completed!"
|
|
152
|
+
)
|
|
153
|
+
result = response
|
|
154
|
+
|
|
155
|
+
except APIError as e:
|
|
156
|
+
progress.update(task, description="[red]✗ Video generation failed")
|
|
157
|
+
console.print(f"[red]Error: {str(e)}[/red]")
|
|
158
|
+
raise click.Abort()
|
|
159
|
+
|
|
160
|
+
table = Table(title="Video Generation Result")
|
|
161
|
+
table.add_column("Field", style="cyan", no_wrap=True)
|
|
162
|
+
table.add_column("Value", style="green", no_wrap=True, overflow="fold")
|
|
163
|
+
|
|
164
|
+
table.add_row("Task ID", result.get("id", ""))
|
|
165
|
+
table.add_row("Status", result.get("status", ""))
|
|
166
|
+
|
|
167
|
+
video_url = result.get("content", {}).get("video_url")
|
|
168
|
+
if video_url:
|
|
169
|
+
table.add_row("Video URL", video_url)
|
|
170
|
+
if return_last_frame and last_frame_url:
|
|
171
|
+
table.add_row("Last Frame URL", last_frame_url)
|
|
172
|
+
if result.get("error_message"):
|
|
173
|
+
table.add_row("Error", result.get("error_message"))
|
|
174
|
+
|
|
175
|
+
console.print(table)
|
|
176
|
+
|
|
177
|
+
if video_url:
|
|
178
|
+
console.print(f"\n[cyan]Complete Video URL:[/cyan]")
|
|
179
|
+
console.print(f"[green]{video_url}[/green]")
|
|
180
|
+
if return_last_frame and last_frame_url:
|
|
181
|
+
console.print(f"\n[cyan]Complete Last Frame URL:[/cyan]")
|
|
182
|
+
console.print(f"[green]{last_frame_url}[/green]")
|
|
183
|
+
|
|
184
|
+
if output:
|
|
185
|
+
with open(output, "w") as f:
|
|
186
|
+
json.dump(result, f, indent=2)
|
|
187
|
+
console.print(f"\n[green]✓[/green] Result saved to: {output}")
|
|
188
|
+
|
|
189
|
+
except Exception as e:
|
|
190
|
+
console.print(f"[red]✗ Error: {str(e)}[/red]")
|
|
191
|
+
raise click.Abort()
|