@plusonelabs/cue 0.0.94 → 0.0.95
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.
- package/bin/cue.js +10 -10
- package/bin/windows-bootstrap.ps1 +9 -9
- package/bin/windows-runtime-artifact.json +2 -2
- package/dist/cli.mjs +1087 -820
- package/dist/skills/README.md +199 -0
- package/dist/skills/_lib/credentials.py +72 -0
- package/dist/skills/activity/SKILL.md +97 -0
- package/dist/skills/assistant/SKILL.md +173 -0
- package/dist/skills/audio/SKILL.md +132 -0
- package/dist/skills/elevenlabs-tts/SKILL.md +76 -0
- package/dist/skills/elevenlabs-tts/scripts/speak.ts +226 -0
- package/dist/skills/event/SKILL.md +98 -0
- package/dist/skills/gemini-search/SKILL.md +52 -0
- package/dist/skills/gemini-search/generate.py +195 -0
- package/dist/skills/image/SKILL.md +169 -0
- package/dist/skills/like/SKILL.md +66 -0
- package/dist/skills/listen/SKILL.md +57 -0
- package/dist/skills/listen/scripts/listen.sh +74 -0
- package/dist/skills/listen/scripts/record.swift +94 -0
- package/dist/skills/markdown-to-pdf/SKILL.md +31 -0
- package/dist/skills/message/SKILL.md +136 -0
- package/dist/skills/mini-apps/SKILL.md +256 -0
- package/dist/skills/music/SKILL.md +139 -0
- package/dist/skills/nano-banana/SKILL.md +70 -0
- package/dist/skills/nano-banana/generate.py +191 -0
- package/dist/skills/news/SKILL.md +41 -0
- package/dist/skills/notify/SKILL.md +123 -0
- package/dist/skills/places/SKILL.md +215 -0
- package/dist/skills/posts/SKILL.md +440 -0
- package/dist/skills/project/SKILL.md +116 -0
- package/dist/skills/pulse/SKILL.md +106 -0
- package/dist/skills/reddit/SKILL.md +41 -0
- package/dist/skills/seeddance/SKILL.md +81 -0
- package/dist/skills/seeddance/generate.py +303 -0
- package/dist/skills/seedream/SKILL.md +86 -0
- package/dist/skills/seedream/generate.py +301 -0
- package/dist/skills/social-graph/SKILL.md +119 -0
- package/dist/skills/transcribe/SKILL.md +150 -0
- package/dist/skills/transcribe/generate.py +389 -0
- package/dist/skills/user/SKILL.md +180 -0
- package/dist/skills/veo3/SKILL.md +76 -0
- package/dist/skills/veo3/generate.py +339 -0
- package/dist/skills/video/SKILL.md +163 -0
- package/dist/skills/weather/SKILL.md +101 -0
- package/dist/skills/web-fetch/SKILL.md +43 -0
- package/dist/skills/web-search/SKILL.md +52 -0
- package/dist/skills/z-asr/SKILL.md +58 -0
- package/dist/skills/z-asr/generate.py +177 -0
- package/dist/skills/z-search/SKILL.md +57 -0
- package/dist/skills/z-search/generate.py +189 -0
- package/dist/skills/z-tts/SKILL.md +51 -0
- package/dist/skills/z-tts/generate.py +172 -0
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: seeddance
|
|
3
|
+
description: Generate videos using ByteDance Doubao SeedAnce API. Use when user asks to generate videos with SeedAnce, Doubao, or ByteDance video models. Supports text-to-video, image-to-video, first/last frame interpolation, and audio generation.
|
|
4
|
+
category: media
|
|
5
|
+
type: hybrid
|
|
6
|
+
env:
|
|
7
|
+
- ARK_API_KEY
|
|
8
|
+
metadata:
|
|
9
|
+
short-description: Generate videos with SeedAnce
|
|
10
|
+
scope: first-party
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Generate videos using ByteDance's Doubao SeedAnce API (Volcengine Ark).
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Python 3.10+, `httpx` package
|
|
18
|
+
- `ARK_API_KEY` environment variable (or configured via `cue skill env set`)
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Text-to-video
|
|
24
|
+
python3 <skill-dir>/generate.py "A field of white daisies under blue sky, camera slowly zooms in"
|
|
25
|
+
|
|
26
|
+
# Image-to-video (animate a reference image)
|
|
27
|
+
python3 <skill-dir>/generate.py "Girl opens her eyes and looks at camera" --image photo.jpg
|
|
28
|
+
|
|
29
|
+
# First + last frame interpolation
|
|
30
|
+
python3 <skill-dir>/generate.py "Girl says cheese, 360 orbit camera" --first-frame start.jpg --last-frame end.jpg
|
|
31
|
+
|
|
32
|
+
# With audio generation
|
|
33
|
+
python3 <skill-dir>/generate.py "Wind blowing through hair" --image photo.jpg --audio
|
|
34
|
+
|
|
35
|
+
# Custom output path
|
|
36
|
+
python3 <skill-dir>/generate.py "A cat walking" --output cat.mp4
|
|
37
|
+
|
|
38
|
+
# Aspect ratios
|
|
39
|
+
python3 <skill-dir>/generate.py "prompt" --ratio 16:9 # Landscape (default)
|
|
40
|
+
python3 <skill-dir>/generate.py "prompt" --ratio 9:16 # Vertical
|
|
41
|
+
python3 <skill-dir>/generate.py "prompt" --ratio 1:1 # Square
|
|
42
|
+
python3 <skill-dir>/generate.py "prompt" --ratio adaptive # Match input image
|
|
43
|
+
|
|
44
|
+
# Duration (seconds)
|
|
45
|
+
python3 <skill-dir>/generate.py "prompt" --duration 5 # 5 seconds (default)
|
|
46
|
+
python3 <skill-dir>/generate.py "prompt" --duration 10 # 10 seconds
|
|
47
|
+
|
|
48
|
+
# Use 1.0 model (1080p text-to-video, no image input)
|
|
49
|
+
python3 <skill-dir>/generate.py "prompt" --v1
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Generation Time:** Typically 30-90 seconds. The script polls automatically and downloads when complete.
|
|
53
|
+
|
|
54
|
+
## Models
|
|
55
|
+
|
|
56
|
+
| Model | ID | Resolution | Features |
|
|
57
|
+
| ---------------- | -------------------------------- | ---------- | ---------------------------------------------------------------- |
|
|
58
|
+
| SeedAnce 1.5 Pro | `doubao-seedance-1-5-pro-251215` | 720p | Text-to-video, image-to-video, first/last frame, audio (default) |
|
|
59
|
+
| SeedAnce 1.0 Pro | `doubao-seedance-1-0-pro-250528` | 1080p | Text-to-video only |
|
|
60
|
+
|
|
61
|
+
## Combining with Image Generation
|
|
62
|
+
|
|
63
|
+
Generate first frame with nano-banana, then animate with seeddance:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 1. Generate image
|
|
67
|
+
python3 <skills-dir>/nano-banana/generate.py "A girl holding a fox in a forest" --output fox_girl.png
|
|
68
|
+
|
|
69
|
+
# 2. Animate the image
|
|
70
|
+
python3 <skills-dir>/seeddance/generate.py "Girl opens eyes, looks at camera, wind blows hair" --image fox_girl.png --audio
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Troubleshooting
|
|
74
|
+
|
|
75
|
+
| Error | Solution |
|
|
76
|
+
| ---------------------- | --------------------------------------------- |
|
|
77
|
+
| "ARK_API_KEY not set" | Export env var: `export ARK_API_KEY=your-key` |
|
|
78
|
+
| "API error: 429" | Rate limited - wait and retry |
|
|
79
|
+
| "API error: 400" | Check prompt or image URL format |
|
|
80
|
+
| "Generation timed out" | Try shorter duration or simpler prompt |
|
|
81
|
+
| "Generation failed" | Check API status or try a different prompt |
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SeedAnce - Video generation using ByteDance Doubao SeedAnce API.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python generate.py "A sunset over mountains"
|
|
7
|
+
python generate.py "prompt" --output video.mp4
|
|
8
|
+
python generate.py "prompt" --image first_frame.jpg
|
|
9
|
+
python generate.py "prompt" --first-frame start.jpg --last-frame end.jpg
|
|
10
|
+
python generate.py "prompt" --image photo.jpg --audio
|
|
11
|
+
python generate.py "prompt" --v1 # Use 1.0 model (1080p, text-only)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
import time
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '_lib'))
|
|
22
|
+
from credentials import get_credential
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
import httpx
|
|
26
|
+
except ImportError:
|
|
27
|
+
print("Error: httpx not installed. Run: pip install httpx")
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
API_URL = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"
|
|
32
|
+
MODEL_V15 = "doubao-seedance-1-5-pro-251215"
|
|
33
|
+
MODEL_V10 = "doubao-seedance-1-0-pro-250528"
|
|
34
|
+
TIMEOUT = 30.0
|
|
35
|
+
POLL_INTERVAL = 5
|
|
36
|
+
MAX_POLL_TIME = 300
|
|
37
|
+
SKILL_DIR = Path(__file__).parent
|
|
38
|
+
ARCHIVE_DIR = SKILL_DIR / "_archive"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def create_task(
|
|
42
|
+
prompt: str,
|
|
43
|
+
model: str = MODEL_V15,
|
|
44
|
+
ratio: str = "16:9",
|
|
45
|
+
duration: int = 5,
|
|
46
|
+
image_url: str | None = None,
|
|
47
|
+
first_frame_url: str | None = None,
|
|
48
|
+
last_frame_url: str | None = None,
|
|
49
|
+
generate_audio: bool = False,
|
|
50
|
+
) -> str:
|
|
51
|
+
api_key = get_credential("ARK_API_KEY", "seeddance")
|
|
52
|
+
|
|
53
|
+
content: list[dict] = [{"type": "text", "text": prompt}]
|
|
54
|
+
|
|
55
|
+
if image_url:
|
|
56
|
+
content.append({
|
|
57
|
+
"type": "image_url",
|
|
58
|
+
"image_url": {"url": image_url},
|
|
59
|
+
})
|
|
60
|
+
if first_frame_url:
|
|
61
|
+
content.append({
|
|
62
|
+
"type": "image_url",
|
|
63
|
+
"image_url": {"url": first_frame_url},
|
|
64
|
+
"role": "first_frame",
|
|
65
|
+
})
|
|
66
|
+
if last_frame_url:
|
|
67
|
+
content.append({
|
|
68
|
+
"type": "image_url",
|
|
69
|
+
"image_url": {"url": last_frame_url},
|
|
70
|
+
"role": "last_frame",
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
body: dict = {
|
|
74
|
+
"model": model,
|
|
75
|
+
"content": content,
|
|
76
|
+
"ratio": ratio,
|
|
77
|
+
"duration": duration,
|
|
78
|
+
"watermark": False,
|
|
79
|
+
}
|
|
80
|
+
if generate_audio:
|
|
81
|
+
body["generate_audio"] = True
|
|
82
|
+
|
|
83
|
+
print(f"Starting video generation with {model}...")
|
|
84
|
+
print(f"Prompt: {prompt[:100]}{'...' if len(prompt) > 100 else ''}")
|
|
85
|
+
|
|
86
|
+
with httpx.Client(timeout=TIMEOUT) as client:
|
|
87
|
+
response = client.post(
|
|
88
|
+
API_URL,
|
|
89
|
+
json=body,
|
|
90
|
+
headers={
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
"Authorization": f"Bearer {api_key}",
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
if response.status_code != 200:
|
|
97
|
+
print(f"Error: API returned {response.status_code}")
|
|
98
|
+
print(response.text[:500])
|
|
99
|
+
sys.exit(1)
|
|
100
|
+
|
|
101
|
+
data = response.json()
|
|
102
|
+
|
|
103
|
+
if "error" in data:
|
|
104
|
+
print(f"Error: {data['error'].get('message', data['error'])}")
|
|
105
|
+
sys.exit(1)
|
|
106
|
+
|
|
107
|
+
task_id = data.get("id")
|
|
108
|
+
if not task_id:
|
|
109
|
+
print("Error: No task ID in response")
|
|
110
|
+
print(data)
|
|
111
|
+
sys.exit(1)
|
|
112
|
+
|
|
113
|
+
return task_id
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def poll_task(task_id: str) -> tuple[bool, str | None, str | None]:
|
|
117
|
+
api_key = get_credential("ARK_API_KEY", "seeddance")
|
|
118
|
+
url = f"{API_URL}/{task_id}"
|
|
119
|
+
|
|
120
|
+
with httpx.Client(timeout=TIMEOUT) as client:
|
|
121
|
+
response = client.get(
|
|
122
|
+
url,
|
|
123
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if response.status_code != 200:
|
|
127
|
+
return False, None, f"Poll error: {response.status_code}"
|
|
128
|
+
|
|
129
|
+
data = response.json()
|
|
130
|
+
|
|
131
|
+
status = data.get("status")
|
|
132
|
+
|
|
133
|
+
if status == "succeeded":
|
|
134
|
+
video_url = data.get("content", {}).get("video_url")
|
|
135
|
+
if video_url:
|
|
136
|
+
resolution = data.get("resolution", "unknown")
|
|
137
|
+
ratio = data.get("ratio", "unknown")
|
|
138
|
+
duration = data.get("duration", "unknown")
|
|
139
|
+
print(f" Completed: {resolution}, {ratio}, {duration}s")
|
|
140
|
+
return True, video_url, None
|
|
141
|
+
return True, None, "No video URL in response"
|
|
142
|
+
|
|
143
|
+
if status == "failed":
|
|
144
|
+
error = data.get("error", {})
|
|
145
|
+
msg = error.get("message", "Unknown error") if isinstance(error, dict) else str(error)
|
|
146
|
+
return True, None, msg
|
|
147
|
+
|
|
148
|
+
return False, None, None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def download_video(video_url: str) -> bytes:
|
|
152
|
+
print("Downloading video...")
|
|
153
|
+
|
|
154
|
+
with httpx.Client(timeout=120.0, follow_redirects=True) as client:
|
|
155
|
+
response = client.get(video_url)
|
|
156
|
+
|
|
157
|
+
if response.status_code != 200:
|
|
158
|
+
print(f"Error: Download failed with {response.status_code}")
|
|
159
|
+
sys.exit(1)
|
|
160
|
+
|
|
161
|
+
return response.content
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def generate_video(
|
|
165
|
+
prompt: str,
|
|
166
|
+
model: str = MODEL_V15,
|
|
167
|
+
ratio: str = "16:9",
|
|
168
|
+
duration: int = 5,
|
|
169
|
+
image_url: str | None = None,
|
|
170
|
+
first_frame_url: str | None = None,
|
|
171
|
+
last_frame_url: str | None = None,
|
|
172
|
+
generate_audio: bool = False,
|
|
173
|
+
) -> bytes:
|
|
174
|
+
task_id = create_task(
|
|
175
|
+
prompt=prompt,
|
|
176
|
+
model=model,
|
|
177
|
+
ratio=ratio,
|
|
178
|
+
duration=duration,
|
|
179
|
+
image_url=image_url,
|
|
180
|
+
first_frame_url=first_frame_url,
|
|
181
|
+
last_frame_url=last_frame_url,
|
|
182
|
+
generate_audio=generate_audio,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
print(f"Task: {task_id}")
|
|
186
|
+
print("Polling for completion...")
|
|
187
|
+
|
|
188
|
+
start_time = time.time()
|
|
189
|
+
while time.time() - start_time < MAX_POLL_TIME:
|
|
190
|
+
done, video_url, error = poll_task(task_id)
|
|
191
|
+
|
|
192
|
+
if done:
|
|
193
|
+
if error:
|
|
194
|
+
print(f"Error: {error}")
|
|
195
|
+
sys.exit(1)
|
|
196
|
+
if video_url:
|
|
197
|
+
return download_video(video_url)
|
|
198
|
+
print("Error: No video URL in completed task")
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
|
|
201
|
+
elapsed = int(time.time() - start_time)
|
|
202
|
+
print(f" Still processing... ({elapsed}s elapsed)")
|
|
203
|
+
time.sleep(POLL_INTERVAL)
|
|
204
|
+
|
|
205
|
+
print(f"Error: Generation timed out after {MAX_POLL_TIME}s")
|
|
206
|
+
sys.exit(1)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def main():
|
|
210
|
+
parser = argparse.ArgumentParser(
|
|
211
|
+
description="Generate videos using ByteDance Doubao SeedAnce API",
|
|
212
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
213
|
+
epilog="""
|
|
214
|
+
Examples:
|
|
215
|
+
%(prog)s "A field of daisies under blue sky"
|
|
216
|
+
%(prog)s "prompt" --output video.mp4
|
|
217
|
+
%(prog)s "Animate this scene" --image https://example.com/photo.jpg
|
|
218
|
+
%(prog)s "Smooth transition" --first-frame https://example.com/start.jpg --last-frame https://example.com/end.jpg
|
|
219
|
+
%(prog)s "Wind blowing" --image https://example.com/photo.jpg --audio
|
|
220
|
+
%(prog)s "prompt" --v1 # 1080p text-to-video
|
|
221
|
+
""",
|
|
222
|
+
)
|
|
223
|
+
parser.add_argument("prompt", help="Video generation prompt")
|
|
224
|
+
parser.add_argument(
|
|
225
|
+
"--output", "-o",
|
|
226
|
+
help="Output file path (default: generated_<timestamp>.mp4)",
|
|
227
|
+
)
|
|
228
|
+
parser.add_argument(
|
|
229
|
+
"--image", "-i",
|
|
230
|
+
help="Input image URL for image-to-video (v1.5 only)",
|
|
231
|
+
)
|
|
232
|
+
parser.add_argument(
|
|
233
|
+
"--first-frame",
|
|
234
|
+
help="First frame image URL for interpolation (v1.5 only)",
|
|
235
|
+
)
|
|
236
|
+
parser.add_argument(
|
|
237
|
+
"--last-frame",
|
|
238
|
+
help="Last frame image URL for interpolation (v1.5 only, requires --first-frame)",
|
|
239
|
+
)
|
|
240
|
+
parser.add_argument(
|
|
241
|
+
"--audio", "-a",
|
|
242
|
+
action="store_true",
|
|
243
|
+
help="Generate audio along with video (v1.5 only)",
|
|
244
|
+
)
|
|
245
|
+
parser.add_argument(
|
|
246
|
+
"--ratio", "-r",
|
|
247
|
+
default="16:9",
|
|
248
|
+
choices=["16:9", "9:16", "1:1", "adaptive"],
|
|
249
|
+
help="Aspect ratio (default: 16:9, use 'adaptive' with image input)",
|
|
250
|
+
)
|
|
251
|
+
parser.add_argument(
|
|
252
|
+
"--duration", "-d",
|
|
253
|
+
type=int,
|
|
254
|
+
default=5,
|
|
255
|
+
help="Video duration in seconds (default: 5)",
|
|
256
|
+
)
|
|
257
|
+
parser.add_argument(
|
|
258
|
+
"--v1",
|
|
259
|
+
action="store_true",
|
|
260
|
+
help=f"Use v1.0 model ({MODEL_V10}) — 1080p text-to-video only",
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
args = parser.parse_args()
|
|
264
|
+
|
|
265
|
+
model = MODEL_V10 if args.v1 else MODEL_V15
|
|
266
|
+
|
|
267
|
+
if args.v1 and (args.image or args.first_frame or args.last_frame or args.audio):
|
|
268
|
+
print("Error: --v1 model only supports text-to-video (no --image, --first-frame, --last-frame, --audio)")
|
|
269
|
+
sys.exit(1)
|
|
270
|
+
|
|
271
|
+
if args.last_frame and not args.first_frame:
|
|
272
|
+
print("Error: --last-frame requires --first-frame")
|
|
273
|
+
sys.exit(1)
|
|
274
|
+
|
|
275
|
+
if args.image and args.first_frame:
|
|
276
|
+
print("Error: use --image for image-to-video OR --first-frame/--last-frame for interpolation, not both")
|
|
277
|
+
sys.exit(1)
|
|
278
|
+
|
|
279
|
+
video_bytes = generate_video(
|
|
280
|
+
prompt=args.prompt,
|
|
281
|
+
model=model,
|
|
282
|
+
ratio=args.ratio,
|
|
283
|
+
duration=args.duration,
|
|
284
|
+
image_url=args.image,
|
|
285
|
+
first_frame_url=args.first_frame,
|
|
286
|
+
last_frame_url=args.last_frame,
|
|
287
|
+
generate_audio=args.audio,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
if args.output:
|
|
291
|
+
output_path = Path(args.output)
|
|
292
|
+
else:
|
|
293
|
+
ARCHIVE_DIR.mkdir(exist_ok=True)
|
|
294
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
295
|
+
output_path = ARCHIVE_DIR / f"generated_{timestamp}.mp4"
|
|
296
|
+
|
|
297
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
298
|
+
output_path.write_bytes(video_bytes)
|
|
299
|
+
print(f"Saved: {output_path} ({len(video_bytes):,} bytes)")
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
if __name__ == "__main__":
|
|
303
|
+
main()
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: seedream
|
|
3
|
+
description: Generate images using ByteDance Doubao Seedream API. Use when user asks to generate images with Seedream, Doubao, or ByteDance image models. Supports text-to-image, image-to-image, multi-image input, and sequential image generation.
|
|
4
|
+
category: media
|
|
5
|
+
type: hybrid
|
|
6
|
+
env:
|
|
7
|
+
- ARK_API_KEY
|
|
8
|
+
metadata:
|
|
9
|
+
short-description: Generate images with Seedream
|
|
10
|
+
scope: first-party
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Generate images using ByteDance's Doubao Seedream API (Volcengine Ark).
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- Python 3.10+, `httpx` package
|
|
18
|
+
- `ARK_API_KEY` environment variable (or configured via `cue skill env set`)
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Text-to-image
|
|
24
|
+
python3 <skill-dir>/generate.py "A cute cat sitting on a windowsill, warm sunlight"
|
|
25
|
+
|
|
26
|
+
# Custom output path
|
|
27
|
+
python3 <skill-dir>/generate.py "A sunset over mountains" --output sunset.png
|
|
28
|
+
|
|
29
|
+
# Image-to-image (reference image + prompt)
|
|
30
|
+
python3 <skill-dir>/generate.py "Make it look like a watercolor painting" --image photo.jpg
|
|
31
|
+
|
|
32
|
+
# Image editing (seededit model)
|
|
33
|
+
python3 <skill-dir>/generate.py "Remove the background" --image photo.jpg --edit
|
|
34
|
+
|
|
35
|
+
# Multiple reference images (up to 14)
|
|
36
|
+
python3 <skill-dir>/generate.py "Combine these styles" --image a.jpg --image b.jpg --image c.jpg
|
|
37
|
+
|
|
38
|
+
# Size options
|
|
39
|
+
python3 <skill-dir>/generate.py "prompt" --size 2K # 2K resolution (default)
|
|
40
|
+
python3 <skill-dir>/generate.py "prompt" --size 4K # 4K resolution
|
|
41
|
+
python3 <skill-dir>/generate.py "prompt" --size 2560x1440 # Custom WxH
|
|
42
|
+
|
|
43
|
+
# Sequential image generation (multiple related images)
|
|
44
|
+
python3 <skill-dir>/generate.py "A four-panel comic about a cat" --sequential
|
|
45
|
+
python3 <skill-dir>/generate.py "prompt" --sequential --max-images 4
|
|
46
|
+
|
|
47
|
+
# Model selection
|
|
48
|
+
python3 <skill-dir>/generate.py "prompt" # Seedream 5.0 (default)
|
|
49
|
+
python3 <skill-dir>/generate.py "prompt" --v45 # Seedream 4.5
|
|
50
|
+
python3 <skill-dir>/generate.py "prompt" --v4 # Seedream 4.0
|
|
51
|
+
python3 <skill-dir>/generate.py "prompt" --v3 # Seedream 3.0 (text-only)
|
|
52
|
+
python3 <skill-dir>/generate.py "prompt" --image x.jpg --edit # SeedEdit 3.0
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Generation Time:** Typically 5-15 seconds.
|
|
56
|
+
|
|
57
|
+
## Models
|
|
58
|
+
|
|
59
|
+
| Model | ID | Features |
|
|
60
|
+
| ------------ | -------------------------------- | ------------------------------------------------------------- |
|
|
61
|
+
| Seedream 5.0 | `doubao-seedream-5-0-260128` | Text/image-to-image, multi-image, sequential, 2K/4K (default) |
|
|
62
|
+
| Seedream 4.5 | `doubao-seedream-4-5-251128` | Text/image-to-image, multi-image, sequential, 2K/4K |
|
|
63
|
+
| Seedream 4.0 | `doubao-seedream-4-0-250828` | Text/image-to-image, multi-image, sequential, 1K/2K/4K |
|
|
64
|
+
| Seedream 3.0 | `doubao-seedream-3-0-t2i-250415` | Text-to-image only |
|
|
65
|
+
| SeedEdit 3.0 | `doubao-seededit-3-0-i2i-250628` | Image editing (single image + prompt) |
|
|
66
|
+
|
|
67
|
+
## Combining with SeedAnce
|
|
68
|
+
|
|
69
|
+
Generate an image with seedream, then animate it with seeddance:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 1. Generate image
|
|
73
|
+
python3 <skills-dir>/seedream/generate.py "A girl holding a fox in a snowy forest" --output fox_girl.png
|
|
74
|
+
|
|
75
|
+
# 2. Animate with seeddance (pass URL or upload first)
|
|
76
|
+
python3 <skills-dir>/seeddance/generate.py "Girl opens eyes, wind blows hair" --image fox_girl.png --audio
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Troubleshooting
|
|
80
|
+
|
|
81
|
+
| Error | Solution |
|
|
82
|
+
| -------------------------- | --------------------------------------------- |
|
|
83
|
+
| "ARK_API_KEY not set" | Export env var: `export ARK_API_KEY=your-key` |
|
|
84
|
+
| "API error: 429" | Rate limited - wait and retry |
|
|
85
|
+
| "API error: 400" | Check prompt or image format |
|
|
86
|
+
| "Content policy violation" | Modify prompt to avoid restricted content |
|