
Pikastream Video Meeting
- 11 installs
- 1.2k repo stars
- Updated July 15, 2026
- pika-labs/pika-skills
pikastream-video-meeting is a Claude Code skill for ai & agent building.
About
pikastream-video-meeting is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- pikastream-video-meeting
- AI & Agent Building
- AI-coding skill
Pikastream Video Meeting by the numbers
- 11 all-time installs (skills.sh)
- Ranked #11,740 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pika-labs/pika-skills --skill pikastream-video-meetingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 11 |
|---|---|
| repo stars | ★ 1.2k |
| Last updated | July 15, 2026 |
| Repository | pika-labs/pika-skills ↗ |
How do I helps with ai & agent building tasks.?
Helps with ai & agent building tasks.
Who is it for?
Best when you're working on ai & agent building and need structured help with pikastream video meeting.
Skip if: Teams with no ai & agent building needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to helps with ai & agent building tasks., or when pikastream-video-meeting is a claude code skill for ai & agent building.
What you get
Structured output aligned to pikastream-video-meeting: pikastream-video-meeting, AI & Agent Building.
Files
PikaStream Video Meeting
Script: SKILL_DIR=skills/pikastream-video-meeting
First-Time Setup
Run once when the skill is first loaded:
pip install -r $SKILL_DIR/requirements.txt1. Avatar
Check if identity/videomeeting-avatar.png exists and is larger than 1 KB. If it does NOT exist (or is too small):
1. Ask the user: I need an avatar image for the video meeting (a headshot or portrait). Send me an image, or say "generate" and I'll create one for you. 2. Do not proceed until the user responds. Do not auto-generate. 3. User sends an image: save it to identity/videomeeting-avatar.png. 4. User says "generate": run:
python $SKILL_DIR/scripts/pikastreaming_videomeeting.py generate-avatar \
--output identity/videomeeting-avatar.pngIf the user describes what they want (e.g. "a cartoon cat"), pass --prompt "<description>, portrait headshot suitable for video calls". Show the generated image. Ask: Want to keep this avatar or regenerate? Wait for reply. 5. Anything else: repeat the question from step 1.
The bot must have an avatar before joining a meeting.
2. Voice
Check if life/voice_id.txt exists and is non-empty.
If it exists: read life/voice_config.json. If readable, check cloned_at — if 6+ days ago, warn the user: Your voice clone was created on {date} and may have expired (cloned voices are deleted after 7 days of non-use). Want to re-clone with a new recording, or try the existing one?
- Re-clone: go to "If it does not exist" below.
- Keep it: use the existing voice ID.
If life/voice_config.json is missing or unreadable, use the voice ID from life/voice_id.txt as-is.
If it does not exist (or user chose to re-clone):
1. Ask the user: I don't have a voice clone yet. You can: (a) send me a voice recording (10s-5min, clear speech) and I'll clone it, or (b) say "skip" to use a default voice. 2. Do not proceed until the user responds. 3. User says "skip": use English_radiant_girl. 4. User sends an audio file: run:
python $SKILL_DIR/scripts/pikastreaming_videomeeting.py clone-voice \
--audio <file> --name <bot-name> --noise-reduction- Exit 0: read
life/voice_id.txt. Tell user:Voice cloned. Using {voice_id} for this meeting. - Exit non-zero: tell user cloning failed (include stderr). Ask:
Try again with a different file, or skip and use the default voice?
5. Invalid file (not audio): respond That doesn't look like a supported audio file. Send an mp3, m4a, wav, ogg, flac, or aac file (10s-5min of clear speech). Wait for retry or "skip".
---
Join Flow
Step 1 — Validate & gather context
Avatar: check identity/videomeeting-avatar.png exists and is > 1 KB. If not, run First-Time Setup above.
Voice: check life/voice_id.txt exists. If not, run the Voice section of First-Time Setup above.
Context: always gather fresh context — do not reuse a stale file from a previous session.
1. Read your workspace files (MEMORY.md, daily logs, identity files, etc.). 2. If no workspace data is available, ask the user: What name should the bot use in this meeting? Use their answer for the Name: field. Fill in any other sections you know from the conversation. 3. Synthesize a concise reference card to /tmp/meeting_system_prompt.txt. Use {name} as the bot's display name (also used as --bot-name). If data is thin (e.g. only a name), keep it short — don't pad with filler.
Synthesize the raw data below into a concise reference card for {name} to use during a voice/video call. Use third-person ("{name}") throughout. Prioritize CONCRETE DETAILS.
PRIORITY ORDER:
1. SPECIFIC FACTS: names, places, dates, numbers, events
2. RECENT ACTIVITY: what happened today/this week — actions, not vibes
3. RELATIONSHIPS: who matters, specific interactions
4. PERSONALITY: 1-2 sentences MAX
CURATION RULES:
- KEEP: anything with a proper noun, a number, a date, or a concrete action
- DROP: vague descriptions, routine status updates, empty entries
- MERGE: if multiple entries say similar things, pick the most vivid one
OUTPUT FORMAT:
**{name}**: [1 sentence — tone/vibe]
**Known facts** (concrete only, max 10):
- [specific fact with names/dates/numbers]
**Recent activity**:
- [built X, fixed Y, went to Z]
**Right now**: [1 line — current activity]
**People**: [name — 1 specific detail each]
RULES:
- Concrete > abstract
- Actions > descriptions
- Do not invent facts
- If data is thin, keep it shortStep 2 — Join
python $SKILL_DIR/scripts/pikastreaming_videomeeting.py join \
--meet-url <url> --bot-name <name> \
--image identity/videomeeting-avatar.png \
--system-prompt-file /tmp/meeting_system_prompt.txt \
--voice-id <id> [--meeting-password <pw>]Tell the user you're in. Say leave to leave. Don't mention session IDs.
Exit codes: 0 = joined. 6 = insufficient credits (stdout JSON contains a checkout_url — show it to the user).
Leave
python $SKILL_DIR/scripts/pikastreaming_videomeeting.py leave \
--session-id <id from join output>requests>=2.32.5
#!/usr/bin/env python
# Copyright 2026 Pika Labs, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""PikaStreaming Video Meeting — join or leave a meeting via PikaStreaming API.
Authenticates through the Pika API proxy (PIKA_API_BASE_URL + PIKA_DEV_KEY).
Requires PIKA_DEV_KEY to be set in the environment before running. When called
non-interactively (e.g. from an agent or CI), the key MUST be pre-configured —
stdin prompts will block indefinitely without a TTY.
Usage:
python pikastreaming_videomeeting.py join --meet-url <url> --bot-name <name> [--voice-id <id>] [--image <path>] [--meeting-password <pw>] [--system-prompt <desc>] [--system-prompt-file <path>] [--timeout-sec 90]
python pikastreaming_videomeeting.py leave --session-id <id>
Exit codes: 0=ok, 2=validation, 3=http, 4=session error, 5=timeout, 6=funding (checkout URL in stdout JSON)
"""
from __future__ import annotations
import argparse
import json
import mimetypes
import os
import sys
import time
from pathlib import Path
import requests
SKILL_DIR = Path(__file__).resolve().parent.parent
DEFAULT_IMAGE = SKILL_DIR / "assets" / "placeholder-avatar.jpg"
DEFAULT_VOICE = "English_radiant_girl"
DEFAULT_API_BASE = "https://7i30hpv4bo9ud5mhianq.pika.art"
PIKA_SENDER_ID = os.environ.get("PIKA_SENDER_ID", "")
PIKA_MESSAGE_CHANNEL = os.environ.get("PIKA_MESSAGE_CHANNEL", "")
def get_sender_headers() -> dict:
"""Return sender attribution headers for proxy billing."""
headers = {}
if PIKA_SENDER_ID:
headers["X-Sender-Id"] = PIKA_SENDER_ID
if PIKA_MESSAGE_CHANNEL:
headers["X-Message-Channel"] = PIKA_MESSAGE_CHANNEL
return headers
def eprint(*a):
print(*a, file=sys.stderr)
def get_api_config() -> tuple[str, dict[str, str]]:
"""Return (api_base, headers) using DevKey."""
base_url = os.environ.get("PIKA_API_BASE_URL", DEFAULT_API_BASE).rstrip("/")
api_base = f"{base_url}/proxy/realtime"
dev_key = os.environ.get("PIKA_DEV_KEY", "").strip()
if not dev_key:
eprint("Error: PIKA_DEV_KEY is required. Get one at https://www.pika.me/dev/login")
sys.exit(1)
headers = {
"Authorization": f"DevKey {dev_key}",
"X-Skill-Name": "pikastream-video-meeting",
**get_sender_headers(),
}
return api_base, headers
def infer_platform(url: str) -> str | None:
u = url.lower()
if "meet.google.com" in u:
return "google_meet"
if "zoom.us" in u or "zoom.com" in u:
return "zoom"
return None
DEVKEY_FILE = Path.home() / ".pika" / "devkey"
SIGNUP_URL = "https://www.pika.me/dev/login"
def get_devkey() -> str:
"""Get DevKey from env or local file. Returns empty string if not found."""
key = os.environ.get("PIKA_DEV_KEY", "").strip()
if key:
return key
if DEVKEY_FILE.exists():
key = DEVKEY_FILE.read_text().strip()
return key
def check_balance(base_url: str, dev_key: str) -> int | None:
"""Return balance or None on error."""
try:
r = requests.get(
f"{base_url}/developer/balance",
headers={"Authorization": f"DevKey {dev_key}"},
timeout=15,
)
if r.ok:
return r.json().get("data", r.json()).get("balance", 0)
eprint(f"Balance check failed: HTTP {r.status_code}")
return None
except Exception as e:
eprint(f"Balance check error: {e}")
return None
def ensure_funded(min_balance: int = 100, poll_interval: int = 10, poll_timeout: int = 300) -> bool:
"""Full funding pipeline. Returns True when funded, False on failure.
Flow:
1. Check DevKey exists → if not, output signup URL and wait for user to provide key
2. Check balance → if funded, return True
3. Auto-create topup checkout → output URL and poll until funded
"""
base_url = os.environ.get("PIKA_API_BASE_URL", DEFAULT_API_BASE).rstrip("/")
# --- Step 1: Ensure DevKey exists ---
dev_key = get_devkey()
if not dev_key:
print(json.dumps({
"status": "no_devkey",
"message": f"No Pika Developer Key found. Sign up at {SIGNUP_URL} to get your API key, then set PIKA_DEV_KEY in the environment.",
"signup_url": SIGNUP_URL,
}))
return False
eprint(f"DevKey: dk_...{dev_key[-4:]}")
auth_headers = {"Authorization": f"DevKey {dev_key}"}
# --- Step 2: Check balance ---
balance = check_balance(base_url, dev_key)
if balance is None:
return False
if balance >= min_balance:
eprint(f"Balance OK: {balance} credits")
print(json.dumps({"status": "funded", "balance": balance}))
return True
eprint(f"Balance ({balance}) below minimum ({min_balance}). Creating topup...")
# --- Step 3: Get products and create checkout ---
try:
r = requests.get(f"{base_url}/developer/topup/products", headers=auth_headers, timeout=15)
products = r.json().get("data", r.json()).get("products", []) if r.ok else []
except Exception:
products = []
if not products:
print(json.dumps({
"status": "needs_topup",
"balance": balance,
"message": f"No credit packs available. Visit {SIGNUP_URL} to top up.",
}))
return False
# Pick smallest sufficient product
deficit = min_balance - balance
products_sorted = sorted(products, key=lambda p: p["numCredits"])
chosen = next((p for p in products_sorted if p["numCredits"] >= deficit), products_sorted[-1])
# Create checkout session
try:
r = requests.post(
f"{base_url}/developer/topup",
headers={**auth_headers, "Content-Type": "application/json"},
json={"product_id": chosen["productId"]},
timeout=15,
)
checkout_url = r.json().get("data", r.json()).get("checkout_url", "") if r.ok else ""
except Exception:
checkout_url = ""
if not checkout_url:
print(json.dumps({"status": "needs_topup", "balance": balance, "message": "Failed to create checkout"}))
return False
print(json.dumps({
"status": "needs_topup",
"balance": balance,
"product": chosen["name"],
"credits": chosen["numCredits"],
"checkout_url": checkout_url,
"message": f"Open the checkout URL to purchase {chosen['name']}. Waiting for payment...",
}))
sys.stdout.flush()
# --- Step 4: Poll until funded ---
eprint(f"Waiting for payment (timeout: {poll_timeout}s)...")
deadline = time.time() + poll_timeout
while time.time() < deadline:
time.sleep(poll_interval)
balance = check_balance(base_url, dev_key)
if balance is not None and balance >= min_balance:
eprint(f"Payment received! Balance: {balance}")
print(json.dumps({"status": "funded", "balance": balance}))
return True
eprint(f" balance: {balance or '?'} — waiting...")
print(json.dumps({"status": "payment_timeout", "message": "Payment not completed in time. Try again."}))
return False
def cmd_join(args):
api_base, auth_headers = get_api_config()
# MANDATORY: full funding pipeline before every join
if not ensure_funded(min_balance=100):
return 6
platform = args.platform or infer_platform(args.meet_url)
if not platform:
eprint("Error: can't infer platform from URL; pass --platform")
return 2
image_src = args.image or str(DEFAULT_IMAGE)
# Resolve system prompt: --system-prompt-file takes priority over --system-prompt
system_prompt = args.system_prompt
if args.system_prompt_file:
sp_path = Path(args.system_prompt_file)
if not sp_path.exists():
eprint(f"Error: system prompt file not found: {sp_path}")
return 2
system_prompt = sp_path.read_text().strip()
tmp_image = None
if image_src.startswith(("http://", "https://")):
import tempfile
eprint(f"Downloading image: {image_src[:80]}...")
try:
r = requests.get(image_src, timeout=15)
r.raise_for_status()
except Exception as e:
eprint(f"Error: failed to download image: {e}")
return 2
suffix = Path(image_src.split("?")[0]).suffix or ".png"
fd, tmp_name = tempfile.mkstemp(suffix=suffix)
tmp = Path(tmp_name)
os.write(fd, r.content)
os.close(fd)
img = tmp
tmp_image = tmp
else:
img = Path(image_src)
try:
if not img.exists() or img.stat().st_size == 0:
eprint(f"Error: image missing: {img}")
return 2
voice = args.voice_id or DEFAULT_VOICE
mime = mimetypes.guess_type(str(img))[0] or "application/octet-stream"
with img.open("rb") as fh:
resp = requests.post(
f"{api_base}/meeting-session",
headers=auth_headers,
files={"image": (img.name, fh, mime)},
data={
"voice_id": voice,
"meet_url": args.meet_url,
"bot_name": args.bot_name,
"platform": platform,
**({"meeting_password": args.meeting_password} if args.meeting_password else {}),
**({"system_prompt": system_prompt} if system_prompt else {}),
},
timeout=180,
)
finally:
if tmp_image and tmp_image.exists():
tmp_image.unlink(missing_ok=True)
if not resp.ok:
eprint(f"Error: HTTP {resp.status_code}: {resp.text[:300]}")
return 3
sid = resp.json().get("session_id")
if not sid:
eprint(f"Error: no session_id: {resp.text[:300]}")
return 3
# Print session_id immediately so agent can capture it
print(json.dumps({"session_id": sid, "platform": platform, "status": "created"}))
sys.stdout.flush()
# Poll — only print on status change to reduce noise
poll_url = f"{api_base}/session/{sid}"
deadline = time.time() + args.timeout_sec
last_status = None
while time.time() < deadline:
time.sleep(2)
try:
r = requests.get(poll_url, headers=auth_headers, timeout=15)
if not r.ok:
continue
d = r.json()
except (requests.RequestException, ValueError):
continue
status = d.get("status")
video = bool(d.get("video_worker_connected") or d.get("video_connected"))
bot = bool(d.get("meeting_bot_connected"))
if status != last_status:
print(json.dumps({"session_id": sid, "status": status, "video": video, "bot": bot}))
sys.stdout.flush()
last_status = status
if status == "ready" or (video and bot):
return 0
if status in ("error", "closed"):
eprint(f"Error: {status}: {d.get('error_message', '')}")
return 4
eprint("Error: timeout")
return 5
def cmd_generate_avatar(args):
"""Generate a default avatar image via OpenAI proxy."""
dev_key = os.environ.get("PIKA_DEV_KEY", "")
base_url = os.environ.get("PIKA_API_BASE_URL", DEFAULT_API_BASE).rstrip("/")
if not dev_key:
eprint("Error: PIKA_DEV_KEY is required")
return 1
prompt = args.prompt or (
"A friendly, approachable portrait headshot of a virtual assistant avatar. "
"Simple, clean background. Professional but warm expression. "
"Photorealistic style, good lighting, centered face, suitable for video calls."
)
eprint("Generating avatar image...")
try:
resp = requests.post(
f"{base_url}/proxy/openai/v1/images/generations",
headers={
"Authorization": f"DevKey {dev_key}",
"Content-Type": "application/json",
"X-Generation-Type": "image",
"X-Model": args.model,
**get_sender_headers(),
},
json={
"model": args.model,
"prompt": prompt,
"size": "1024x1024",
"n": 1,
"quality": "medium",
"output_format": "png",
},
timeout=120,
)
except requests.RequestException as e:
eprint(f"Error: request failed: {e}")
return 3
if not resp.ok:
eprint(f"Error: HTTP {resp.status_code}: {resp.text[:300]}")
return 3
try:
data = resp.json()["data"][0]
except (KeyError, IndexError, ValueError):
eprint(f"Error: unexpected response: {resp.text[:300]}")
return 3
import base64
if "b64_json" in data:
img_bytes = base64.b64decode(data["b64_json"])
elif "url" in data:
eprint("Downloading generated image...")
try:
dl = requests.get(data["url"], timeout=30)
dl.raise_for_status()
img_bytes = dl.content
except Exception as e:
eprint(f"Error: failed to download: {e}")
return 3
else:
eprint("Error: no image in response")
return 3
out = Path(args.output)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_bytes(img_bytes)
print(json.dumps({"path": str(out), "size_bytes": len(img_bytes)}))
return 0
NATIVE_AUDIO_FORMATS = [".mp3", ".m4a", ".wav"]
CONVERTIBLE_AUDIO_FORMATS = [".ogg", ".mp4", ".webm", ".mkv", ".mov", ".flac", ".aac", ".wma", ".opus"]
def convert_to_mp3(input_file: str) -> str:
"""Convert audio file to mp3 using ffmpeg. Returns path to converted file."""
import subprocess
import tempfile
fd, tmp = tempfile.mkstemp(suffix=".mp3")
os.close(fd)
try:
subprocess.run(
["ffmpeg", "-i", input_file, "-codec:a", "libmp3lame", "-b:a", "128k", tmp, "-y"],
check=True,
capture_output=True,
)
except FileNotFoundError:
os.unlink(tmp)
eprint("Error: ffmpeg is required for audio conversion but was not found.")
return ""
except subprocess.CalledProcessError as e:
os.unlink(tmp)
eprint(f"Error: ffmpeg conversion failed: {e.stderr.decode()}")
return ""
return tmp
def prepare_audio(audio_path: str) -> str | None:
"""Ensure audio is in a format the APIs accept. Returns path (may be a temp file)."""
ext = os.path.splitext(audio_path)[1].lower()
if ext in NATIVE_AUDIO_FORMATS:
return audio_path
if ext in CONVERTIBLE_AUDIO_FORMATS:
eprint(f"Converting {ext} to mp3...")
converted = convert_to_mp3(audio_path)
return converted or None
eprint(f"Warning: {ext} may not be supported. Attempting upload anyway...")
return audio_path
def clone_voice(base_url: str, api_key: str, audio_path: str, voice_name: str,
noise_reduction: bool = False) -> dict | None:
"""Clone a voice via the Pika voice proxy."""
from datetime import datetime, timezone
headers = {"Authorization": f"DevKey {api_key}", **get_sender_headers()}
ext = os.path.splitext(audio_path)[1].lower()
content_type = {".mp3": "audio/mpeg", ".m4a": "audio/mp4", ".wav": "audio/wav"}.get(ext, "audio/mpeg")
eprint("Uploading audio for voice cloning...")
try:
with open(audio_path, "rb") as f:
resp = requests.post(
f"{base_url}/proxy/minimax/v1/files/upload",
headers=headers,
files={"file": (os.path.basename(audio_path), f, content_type)},
data={"purpose": "voice_clone"},
timeout=60,
)
resp.raise_for_status()
result = resp.json()
except Exception as e:
eprint(f"Error: upload failed: {e}")
return None
if "base_resp" in result:
if result["base_resp"].get("status_code", 0) != 0:
eprint(f"Error: voice upload: {result['base_resp'].get('status_msg', 'unknown')}")
return None
file_id = None
if "file" in result and isinstance(result["file"], dict):
file_id = result["file"].get("file_id")
file_id = file_id or result.get("file_id") or result.get("id")
if not file_id:
eprint(f"Error: no file_id in upload response: {json.dumps(result)[:200]}")
return None
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
voice_id = f"voice_{voice_name}_{timestamp}"
eprint(f"Cloning voice as {voice_id}...")
try:
resp = requests.post(
f"{base_url}/proxy/minimax/v1/voice_clone",
headers={**headers, "Content-Type": "application/json"},
json={
"file_id": file_id,
"voice_id": voice_id,
"model": "speech-2.8-hd",
"need_noise_reduction": noise_reduction,
"need_volume_normalization": False,
},
timeout=60,
)
resp.raise_for_status()
result = resp.json()
except Exception as e:
eprint(f"Error: clone failed: {e}")
return None
if "base_resp" in result:
if result["base_resp"].get("status_code", 0) != 0:
eprint(f"Error: voice clone: {result['base_resp'].get('status_msg', 'unknown')}")
return None
return {
"voice_id": voice_id,
"provider": "pika",
"cloned_at": datetime.now(timezone.utc).isoformat(),
"source_audio": os.path.basename(audio_path),
"retention_warning": "Cloned voices may be deleted after 7 days of non-use",
}
def cmd_clone_voice(args):
"""Clone a voice from an audio file via the Pika voice proxy."""
dev_key = os.environ.get("PIKA_DEV_KEY", "")
base_url = os.environ.get("PIKA_API_BASE_URL", DEFAULT_API_BASE).rstrip("/")
if not dev_key:
eprint("Error: PIKA_DEV_KEY is required")
return 1
audio_path = args.audio
if not os.path.exists(audio_path):
eprint(f"Error: audio file not found: {audio_path}")
return 2
prepared = prepare_audio(audio_path)
if not prepared:
return 2
tmp_audio = prepared if prepared != audio_path else None
try:
result = clone_voice(base_url, dev_key, prepared, args.name,
noise_reduction=args.noise_reduction)
finally:
if tmp_audio and os.path.exists(tmp_audio):
os.unlink(tmp_audio)
if not result:
return 3
life_dir = Path("life")
life_dir.mkdir(parents=True, exist_ok=True)
(life_dir / "voice_id.txt").write_text(result["voice_id"])
config = {
"voice_id": result["voice_id"],
"provider": result["provider"],
"cloned_at": result["cloned_at"],
"source_audio": result["source_audio"],
}
if "retention_warning" in result:
config["retention_warning"] = result["retention_warning"]
with open(life_dir / "voice_config.json", "w") as f:
json.dump(config, f, indent=2)
print(json.dumps(result))
return 0
def cmd_leave(args):
api_base, auth_headers = get_api_config()
r = requests.delete(
f"{api_base}/session/{args.session_id}",
headers=auth_headers,
timeout=30,
)
if not r.ok:
eprint(f"Error: HTTP {r.status_code}: {r.text[:300]}")
return 3
print(json.dumps({"session_id": args.session_id, "closed": True}))
return 0
def main():
p = argparse.ArgumentParser()
sub = p.add_subparsers(dest="cmd", required=True)
j = sub.add_parser("join")
j.add_argument("--meet-url", required=True)
j.add_argument("--platform", choices=["google_meet", "zoom"])
j.add_argument("--bot-name", required=True)
j.add_argument("--voice-id")
j.add_argument("--meeting-password")
j.add_argument("--system-prompt", help="System prompt text for the meeting bot")
j.add_argument("--system-prompt-file", help="Path to file containing fallback system prompt")
j.add_argument("--image")
j.add_argument("--timeout-sec", type=int, default=90)
lv = sub.add_parser("leave")
lv.add_argument("--session-id", required=True)
ga = sub.add_parser("generate-avatar")
ga.add_argument("--output", required=True, help="Path to save the generated image")
ga.add_argument("--prompt", help="Custom prompt for avatar generation")
ga.add_argument("--model", default="gpt-image-1-mini", help="OpenAI image model")
cv = sub.add_parser("clone-voice")
cv.add_argument("--audio", required=True, help="Audio file (10s-5min, clear speech)")
cv.add_argument("--name", required=True, help="Name for the cloned voice")
cv.add_argument("--noise-reduction", action="store_true", help="Enable noise reduction")
args = p.parse_args()
cmds = {
"join": cmd_join,
"leave": cmd_leave,
"generate-avatar": cmd_generate_avatar,
"clone-voice": cmd_clone_voice,
}
return cmds[args.cmd](args)
if __name__ == "__main__":
raise SystemExit(main())
Related skills
FAQ
What does pikastream-video-meeting do?
pikastream-video-meeting is a Claude Code skill for ai & agent building.
When should I use pikastream-video-meeting?
When you need to helps with ai & agent building tasks., or when pikastream-video-meeting is a claude code skill for ai & agent building.
What are the main capabilities?
pikastream-video-meeting; AI & Agent Building; AI-coding skill.