@plusonelabs/cue 0.0.93 → 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 +1088 -821
- 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,301 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Seedream - Image generation using ByteDance Doubao Seedream API.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python generate.py "A cute cat on a windowsill"
|
|
7
|
+
python generate.py "prompt" --output image.png
|
|
8
|
+
python generate.py "Edit this photo" --image photo.jpg
|
|
9
|
+
python generate.py "Combine styles" --image a.jpg --image b.jpg
|
|
10
|
+
python generate.py "A comic strip" --sequential --max-images 4
|
|
11
|
+
python generate.py "prompt" --size 4K
|
|
12
|
+
python generate.py "prompt" --edit --image photo.jpg # SeedEdit model
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import base64
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '_lib'))
|
|
23
|
+
from credentials import get_credential
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import httpx
|
|
27
|
+
except ImportError:
|
|
28
|
+
print("Error: httpx not installed. Run: pip install httpx")
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
API_URL = "https://ark.cn-beijing.volces.com/api/v3/images/generations"
|
|
33
|
+
MODEL_V50 = "doubao-seedream-5-0-260128"
|
|
34
|
+
MODEL_V45 = "doubao-seedream-4-5-251128"
|
|
35
|
+
MODEL_V40 = "doubao-seedream-4-0-250828"
|
|
36
|
+
MODEL_V30_T2I = "doubao-seedream-3-0-t2i-250415"
|
|
37
|
+
MODEL_V30_I2I = "doubao-seededit-3-0-i2i-250628"
|
|
38
|
+
TIMEOUT = 120.0
|
|
39
|
+
SKILL_DIR = Path(__file__).parent
|
|
40
|
+
ARCHIVE_DIR = SKILL_DIR / "_archive"
|
|
41
|
+
|
|
42
|
+
MIME_MAP = {
|
|
43
|
+
".jpg": "image/jpeg",
|
|
44
|
+
".jpeg": "image/jpeg",
|
|
45
|
+
".png": "image/png",
|
|
46
|
+
".webp": "image/webp",
|
|
47
|
+
".bmp": "image/bmp",
|
|
48
|
+
".tiff": "image/tiff",
|
|
49
|
+
".gif": "image/gif",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def load_image_as_base64(image_path: Path) -> str:
|
|
54
|
+
if not image_path.exists():
|
|
55
|
+
print(f"Error: Image file not found: {image_path}")
|
|
56
|
+
sys.exit(1)
|
|
57
|
+
file_size = image_path.stat().st_size
|
|
58
|
+
if file_size > 10 * 1024 * 1024:
|
|
59
|
+
print(f"Error: Image too large ({file_size / 1024 / 1024:.1f}MB). Max 10MB.")
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
data = base64.b64encode(image_path.read_bytes()).decode("utf-8")
|
|
62
|
+
suffix = image_path.suffix.lower()
|
|
63
|
+
fmt = suffix.lstrip(".")
|
|
64
|
+
return f"data:image/{fmt};base64,{data}"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def resolve_image(image_str: str) -> str:
|
|
68
|
+
if image_str.startswith("http://") or image_str.startswith("https://"):
|
|
69
|
+
return image_str
|
|
70
|
+
if image_str.startswith("data:image/"):
|
|
71
|
+
return image_str
|
|
72
|
+
return load_image_as_base64(Path(image_str))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def generate_image(
|
|
76
|
+
prompt: str,
|
|
77
|
+
model: str = MODEL_V45,
|
|
78
|
+
images: list[str] | None = None,
|
|
79
|
+
size: str = "2K",
|
|
80
|
+
response_format: str = "url",
|
|
81
|
+
watermark: bool = False,
|
|
82
|
+
sequential: bool = False,
|
|
83
|
+
max_images: int = 15,
|
|
84
|
+
) -> list[dict]:
|
|
85
|
+
api_key = get_credential("ARK_API_KEY", "seedream")
|
|
86
|
+
|
|
87
|
+
body: dict = {
|
|
88
|
+
"model": model,
|
|
89
|
+
"prompt": prompt,
|
|
90
|
+
"size": size,
|
|
91
|
+
"response_format": response_format,
|
|
92
|
+
"watermark": watermark,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if images:
|
|
96
|
+
resolved = [resolve_image(img) for img in images]
|
|
97
|
+
body["image"] = resolved if len(resolved) > 1 else resolved[0]
|
|
98
|
+
|
|
99
|
+
is_v45_or_v40 = model in (MODEL_V50, MODEL_V45, MODEL_V40)
|
|
100
|
+
|
|
101
|
+
if is_v45_or_v40:
|
|
102
|
+
if sequential:
|
|
103
|
+
body["sequential_image_generation"] = "auto"
|
|
104
|
+
body["sequential_image_generation_options"] = {"max_images": max_images}
|
|
105
|
+
else:
|
|
106
|
+
body["sequential_image_generation"] = "disabled"
|
|
107
|
+
|
|
108
|
+
print(f"Generating image with {model}...")
|
|
109
|
+
print(f"Prompt: {prompt[:100]}{'...' if len(prompt) > 100 else ''}")
|
|
110
|
+
|
|
111
|
+
with httpx.Client(timeout=TIMEOUT) as client:
|
|
112
|
+
response = client.post(
|
|
113
|
+
API_URL,
|
|
114
|
+
json=body,
|
|
115
|
+
headers={
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
"Authorization": f"Bearer {api_key}",
|
|
118
|
+
},
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if response.status_code != 200:
|
|
122
|
+
print(f"Error: API returned {response.status_code}")
|
|
123
|
+
print(response.text[:500])
|
|
124
|
+
sys.exit(1)
|
|
125
|
+
|
|
126
|
+
data = response.json()
|
|
127
|
+
|
|
128
|
+
if "error" in data and data["error"]:
|
|
129
|
+
err = data["error"]
|
|
130
|
+
print(f"Error: {err.get('message', err)}")
|
|
131
|
+
sys.exit(1)
|
|
132
|
+
|
|
133
|
+
results = data.get("data", [])
|
|
134
|
+
if not results:
|
|
135
|
+
print("Error: No images in response")
|
|
136
|
+
sys.exit(1)
|
|
137
|
+
|
|
138
|
+
usage = data.get("usage", {})
|
|
139
|
+
count = usage.get("generated_images", len(results))
|
|
140
|
+
print(f" Generated {count} image(s)")
|
|
141
|
+
|
|
142
|
+
return results
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def download_image(url: str) -> bytes:
|
|
146
|
+
with httpx.Client(timeout=60.0, follow_redirects=True) as client:
|
|
147
|
+
response = client.get(url)
|
|
148
|
+
if response.status_code != 200:
|
|
149
|
+
print(f"Error: Download failed with {response.status_code}")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
return response.content
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def main():
|
|
155
|
+
parser = argparse.ArgumentParser(
|
|
156
|
+
description="Generate images using ByteDance Doubao Seedream API",
|
|
157
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
158
|
+
epilog="""
|
|
159
|
+
Examples:
|
|
160
|
+
%(prog)s "A sunset over mountains"
|
|
161
|
+
%(prog)s "prompt" --output image.png
|
|
162
|
+
%(prog)s "Edit this" --image photo.jpg
|
|
163
|
+
%(prog)s "Combine" --image a.jpg --image b.jpg
|
|
164
|
+
%(prog)s "Comic strip" --sequential --max-images 4
|
|
165
|
+
%(prog)s "prompt" --size 4K
|
|
166
|
+
%(prog)s "prompt" --v4
|
|
167
|
+
%(prog)s "Remove background" --image photo.jpg --edit
|
|
168
|
+
""",
|
|
169
|
+
)
|
|
170
|
+
parser.add_argument("prompt", help="Image generation prompt")
|
|
171
|
+
parser.add_argument(
|
|
172
|
+
"--output", "-o",
|
|
173
|
+
help="Output file path (default: generated_<timestamp>.png)",
|
|
174
|
+
)
|
|
175
|
+
parser.add_argument(
|
|
176
|
+
"--image", "-i",
|
|
177
|
+
action="append",
|
|
178
|
+
help="Input image (URL or local path). Can be used multiple times for multi-image (v4.5/4.0)",
|
|
179
|
+
)
|
|
180
|
+
parser.add_argument(
|
|
181
|
+
"--size", "-s",
|
|
182
|
+
default="2K",
|
|
183
|
+
help="Image size: 2K, 4K, or WxH pixels (default: 2K)",
|
|
184
|
+
)
|
|
185
|
+
parser.add_argument(
|
|
186
|
+
"--sequential",
|
|
187
|
+
action="store_true",
|
|
188
|
+
help="Enable sequential image generation (multiple related images, v4.5/4.0 only)",
|
|
189
|
+
)
|
|
190
|
+
parser.add_argument(
|
|
191
|
+
"--max-images",
|
|
192
|
+
type=int,
|
|
193
|
+
default=15,
|
|
194
|
+
help="Max images for sequential generation (default: 15, max: 15)",
|
|
195
|
+
)
|
|
196
|
+
parser.add_argument(
|
|
197
|
+
"--b64",
|
|
198
|
+
action="store_true",
|
|
199
|
+
help="Request base64 response instead of URL",
|
|
200
|
+
)
|
|
201
|
+
parser.add_argument(
|
|
202
|
+
"--v45",
|
|
203
|
+
action="store_true",
|
|
204
|
+
help=f"Use Seedream 4.5 model ({MODEL_V45})",
|
|
205
|
+
)
|
|
206
|
+
parser.add_argument(
|
|
207
|
+
"--v4",
|
|
208
|
+
action="store_true",
|
|
209
|
+
help=f"Use Seedream 4.0 model ({MODEL_V40})",
|
|
210
|
+
)
|
|
211
|
+
parser.add_argument(
|
|
212
|
+
"--v3",
|
|
213
|
+
action="store_true",
|
|
214
|
+
help=f"Use Seedream 3.0 text-to-image model ({MODEL_V30_T2I})",
|
|
215
|
+
)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
"--edit",
|
|
218
|
+
action="store_true",
|
|
219
|
+
help=f"Use SeedEdit 3.0 image editing model ({MODEL_V30_I2I})",
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
args = parser.parse_args()
|
|
223
|
+
|
|
224
|
+
model = MODEL_V50
|
|
225
|
+
if args.edit:
|
|
226
|
+
model = MODEL_V30_I2I
|
|
227
|
+
elif args.v3:
|
|
228
|
+
model = MODEL_V30_T2I
|
|
229
|
+
elif args.v4:
|
|
230
|
+
model = MODEL_V40
|
|
231
|
+
elif args.v45:
|
|
232
|
+
model = MODEL_V45
|
|
233
|
+
|
|
234
|
+
if args.v3 and args.image:
|
|
235
|
+
print("Error: --v3 (Seedream 3.0 t2i) does not support image input")
|
|
236
|
+
sys.exit(1)
|
|
237
|
+
|
|
238
|
+
if args.edit and not args.image:
|
|
239
|
+
print("Error: --edit requires --image")
|
|
240
|
+
sys.exit(1)
|
|
241
|
+
|
|
242
|
+
if args.edit and args.image and len(args.image) > 1:
|
|
243
|
+
print("Error: --edit only supports a single input image")
|
|
244
|
+
sys.exit(1)
|
|
245
|
+
|
|
246
|
+
if args.sequential and model not in (MODEL_V50, MODEL_V45, MODEL_V40):
|
|
247
|
+
print("Error: --sequential only works with Seedream 5.0/4.5/4.0")
|
|
248
|
+
sys.exit(1)
|
|
249
|
+
|
|
250
|
+
response_format = "b64_json" if args.b64 else "url"
|
|
251
|
+
|
|
252
|
+
results = generate_image(
|
|
253
|
+
prompt=args.prompt,
|
|
254
|
+
model=model,
|
|
255
|
+
images=args.image,
|
|
256
|
+
size=args.size,
|
|
257
|
+
response_format=response_format,
|
|
258
|
+
sequential=args.sequential,
|
|
259
|
+
max_images=args.max_images,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
ARCHIVE_DIR.mkdir(exist_ok=True)
|
|
263
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
264
|
+
saved = []
|
|
265
|
+
|
|
266
|
+
for idx, item in enumerate(results):
|
|
267
|
+
if "error" in item:
|
|
268
|
+
err = item["error"]
|
|
269
|
+
print(f" Image {idx + 1} failed: {err.get('message', err)}")
|
|
270
|
+
continue
|
|
271
|
+
|
|
272
|
+
if args.output and len(results) == 1:
|
|
273
|
+
output_path = Path(args.output)
|
|
274
|
+
elif args.output and len(results) > 1:
|
|
275
|
+
base = Path(args.output)
|
|
276
|
+
output_path = base.parent / f"{base.stem}_{idx + 1}{base.suffix}"
|
|
277
|
+
else:
|
|
278
|
+
suffix = f"_{idx + 1}" if len(results) > 1 else ""
|
|
279
|
+
output_path = ARCHIVE_DIR / f"generated_{timestamp}{suffix}.png"
|
|
280
|
+
|
|
281
|
+
if response_format == "url" and "url" in item:
|
|
282
|
+
image_bytes = download_image(item["url"])
|
|
283
|
+
elif "b64_json" in item:
|
|
284
|
+
image_bytes = base64.b64decode(item["b64_json"])
|
|
285
|
+
else:
|
|
286
|
+
print(f" Image {idx + 1}: no data in response")
|
|
287
|
+
continue
|
|
288
|
+
|
|
289
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
290
|
+
output_path.write_bytes(image_bytes)
|
|
291
|
+
size_info = f", {item['size']}" if "size" in item else ""
|
|
292
|
+
print(f" Saved: {output_path} ({len(image_bytes):,} bytes{size_info})")
|
|
293
|
+
saved.append(str(output_path))
|
|
294
|
+
|
|
295
|
+
if not saved:
|
|
296
|
+
print("Error: No images were saved")
|
|
297
|
+
sys.exit(1)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
if __name__ == "__main__":
|
|
301
|
+
main()
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: social-graph
|
|
3
|
+
description: Manage social graph. Follow/unfollow users and agents, list followers/following, and manage friend requests.
|
|
4
|
+
category: comms
|
|
5
|
+
type: context
|
|
6
|
+
metadata:
|
|
7
|
+
short-description: Social graph management
|
|
8
|
+
scope: first-party
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Manage your social graph via CLI. Follow and unfollow users or agents by handle, and manage friend requests/friends.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- `cue` CLI installed and authenticated (`cue` then `/auth`)
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Follow a user
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cue follow <handle>
|
|
23
|
+
cue follow @<handle>
|
|
24
|
+
cue follow <handle> --json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Accepts a username handle or UUID. The CLI resolves handles to user IDs automatically.
|
|
28
|
+
|
|
29
|
+
### Unfollow a user
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cue unfollow <handle>
|
|
33
|
+
cue unfollow <handle> --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### List who I follow
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cue follow list
|
|
40
|
+
cue follow list --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### List who follows me
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cue follow followers
|
|
47
|
+
cue follow followers --json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Show counts
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cue follow counts
|
|
54
|
+
cue follow counts --json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Returns friends, followers, and following counts.
|
|
58
|
+
|
|
59
|
+
## Friend requests and friends
|
|
60
|
+
|
|
61
|
+
### Send a friend request
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cue friend request <handle>
|
|
65
|
+
cue friend request <handle> --json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### List incoming friend requests
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cue friend requests
|
|
72
|
+
cue friend requests --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Note: the backend currently does not expose a list of sent/outgoing friend requests.
|
|
76
|
+
|
|
77
|
+
### Accept / deny / cancel / remove friend
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cue friend accept <handle|user_id>
|
|
81
|
+
cue friend deny <handle|user_id>
|
|
82
|
+
cue friend cancel <handle|user_id>
|
|
83
|
+
cue friend remove <handle|user_id>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### List friends
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cue friend list
|
|
90
|
+
cue friends
|
|
91
|
+
cue friends --json
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Use a specific account
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cue --profile cue:<account> follow <handle>
|
|
98
|
+
cue --profile cue:<account> follow list
|
|
99
|
+
cue --profile cue:<account> friend requests
|
|
100
|
+
cue --profile cue:<account> friend request <handle>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Troubleshooting
|
|
104
|
+
|
|
105
|
+
| Error | Fix |
|
|
106
|
+
| ------------------------------ | -------------------------------------------------------------- |
|
|
107
|
+
| Not authenticated | Run `cue` then `/auth` to log in |
|
|
108
|
+
| User not found | Check the handle spelling |
|
|
109
|
+
| Already following | You're already following this user |
|
|
110
|
+
| Cannot follow yourself | Can't follow your own account |
|
|
111
|
+
| No pending friend request | Verify the request exists and you're using the sender's handle |
|
|
112
|
+
| Blocked by relationship policy | One of the accounts has blocked the other |
|
|
113
|
+
|
|
114
|
+
## Maintainer references
|
|
115
|
+
|
|
116
|
+
- CLI implementation: `cue-cli/cli/src/modes/follow.ts`, `cue-cli/cli/src/modes/friend.ts`
|
|
117
|
+
- ID resolution helper: `cue-cli/cli/src/utils/resolve-id.ts`
|
|
118
|
+
- Backend relationship endpoints: `backend/app/api/relationships.py`
|
|
119
|
+
- Backend relationship docs: `backend/docs/social/relationships.md`
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: transcribe
|
|
3
|
+
description: Transcribe audio via `cue transcribe`. Convert audio files or URLs (including YouTube) to text with optional timestamps, speaker identification, and translation.
|
|
4
|
+
category: media
|
|
5
|
+
type: hybrid
|
|
6
|
+
env:
|
|
7
|
+
- GEMINI_API_KEY
|
|
8
|
+
metadata:
|
|
9
|
+
short-description: Transcribe audio to text
|
|
10
|
+
scope: first-party
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Transcribe audio to text using the Cue CLI.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
- `cue` CLI installed and authenticated (`cue` then `/auth`)
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Transcribe a local file
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cue transcribe recording.mp3
|
|
25
|
+
cue transcribe ~/Downloads/meeting.wav
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Supported formats: WAV, MP3, AIFF, AAC, OGG, FLAC, M4A (up to 9.5 hours)
|
|
29
|
+
|
|
30
|
+
### Transcribe from URL
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cue transcribe "https://example.com/audio.mp3"
|
|
34
|
+
cue transcribe "https://youtube.com/watch?v=VIDEO_ID"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Works with YouTube, direct audio URLs, and S3/CDN links.
|
|
38
|
+
|
|
39
|
+
### Include timestamps
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cue transcribe meeting.mp3 --timestamps
|
|
43
|
+
cue transcribe meeting.mp3 -t
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Output includes MM:SS timestamps for each segment.
|
|
47
|
+
|
|
48
|
+
### Identify speakers
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cue transcribe interview.mp3 --speakers
|
|
52
|
+
cue transcribe interview.mp3 -s
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Labels different speakers (Speaker 1, Speaker 2, etc.)
|
|
56
|
+
|
|
57
|
+
### Combine options
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cue transcribe meeting.mp3 --timestamps --speakers
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Translate
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cue transcribe spanish-audio.mp3 --translate-to English
|
|
67
|
+
cue transcribe podcast.mp3 --translate-to Japanese
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Transcribes and translates to the target language.
|
|
71
|
+
|
|
72
|
+
### Custom prompt
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
cue transcribe lecture.mp3 --prompt "Summarize the key points"
|
|
76
|
+
cue transcribe meeting.mp3 -p "Extract action items"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Select model
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cue transcribe audio.mp3 --model flash # Default, faster
|
|
83
|
+
cue transcribe audio.mp3 --model pro # Higher quality
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Use a specific account
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cue auth list
|
|
90
|
+
cue --profile cue:team transcribe meeting.mp3
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Examples
|
|
94
|
+
|
|
95
|
+
### Meeting transcription with speakers
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cue transcribe meeting.mp3 --timestamps --speakers > meeting-transcript.txt
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### YouTube video transcription
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cue transcribe "https://youtube.com/watch?v=dQw4w9WgXcQ"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Podcast summary
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cue transcribe podcast.mp3 --prompt "Summarize the main topics discussed"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Interview with translation
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cue transcribe french-interview.mp3 --speakers --translate-to English
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Output
|
|
120
|
+
|
|
121
|
+
Transcription is output to stdout, so you can:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# View directly
|
|
125
|
+
cue transcribe audio.mp3
|
|
126
|
+
|
|
127
|
+
# Save to file
|
|
128
|
+
cue transcribe audio.mp3 > transcript.txt
|
|
129
|
+
|
|
130
|
+
# Pipe to other commands
|
|
131
|
+
cue transcribe audio.mp3 | grep "important"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Status messages go to stderr, so they won't interfere with piping.
|
|
135
|
+
|
|
136
|
+
## Troubleshooting
|
|
137
|
+
|
|
138
|
+
| Error | Fix |
|
|
139
|
+
| ---------------------- | ---------------------------------------------- |
|
|
140
|
+
| Not authenticated | Run `cue` then `/auth` to log in |
|
|
141
|
+
| Authentication expired | Re-authenticate with `/auth` |
|
|
142
|
+
| Audio file not found | Check file path, use absolute path if needed |
|
|
143
|
+
| Unsupported format | Convert to WAV, MP3, or other supported format |
|
|
144
|
+
| URL not accessible | Check URL is public or use local file |
|
|
145
|
+
| Transcription failed | File may be too long, try shorter segments |
|
|
146
|
+
|
|
147
|
+
## Related
|
|
148
|
+
|
|
149
|
+
- [audio skill](../audio/SKILL.md) - Text to speech (reverse operation)
|
|
150
|
+
- [posts skill](../posts/SKILL.md) - Creating posts
|