pikastream-video-meeting

Par elophanto · elophanto

Rejoindre un appel Google Meet ou Zoom en tant qu'agent de réunion vidéo via PikaStreaming. Déclencheur : l'utilisateur dépose un lien Google Meet ou Zoom, ou demande à rejoindre une réunion.

npx skills add https://github.com/elophanto/elophanto --skill pikastream-video-meeting

PikaStream Video Meeting

Script : SKILL_DIR=skills/pikastream-video-meeting

Configuration initiale

À exécuter une seule fois au premier chargement du skill :

pip install -r $SKILL_DIR/requirements.txt

1. Avatar

Vérifier que identity/videomeeting-avatar.png existe et fait plus de 1 KB. Si ce n'est PAS le cas (ou le fichier est trop petit) :

  1. Demander à l'utilisateur : 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. Ne pas continuer tant que l'utilisateur n'a pas répondu. Ne pas générer automatiquement.
  3. L'utilisateur envoie une image : la sauvegarder dans identity/videomeeting-avatar.png.
  4. L'utilisateur dit "generate" : exécuter :
    python $SKILL_DIR/scripts/pikastreaming_videomeeting.py generate-avatar \
      --output identity/videomeeting-avatar.png

    Si l'utilisateur décrit ce qu'il veut (par ex. « a cartoon cat »), transmettre --prompt "<description>, portrait headshot suitable for video calls". Afficher l'image générée. Demander : Want to keep this avatar or regenerate? Attendre la réponse.

  5. Autre réponse : répéter la question de l'étape 1.

Le bot doit avoir un avatar avant de rejoindre une réunion.

2. Voice

Vérifier que life/voice_id.txt existe et n'est pas vide.

S'il existe : lire life/voice_config.json. S'il est lisible, vérifier cloned_at — si c'était il y a 6+ jours, avertir l'utilisateur : 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-cloner : aller à « S'il n'existe pas » ci-dessous.
  • Le garder : utiliser l'ID voice existant.

Si life/voice_config.json est manquant ou illisible, utiliser l'ID voice de life/voice_id.txt tel quel.

S'il n'existe pas (ou l'utilisateur a choisi de re-cloner) :

  1. Demander à l'utilisateur : 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. Ne pas continuer tant que l'utilisateur n'a pas répondu.
  3. L'utilisateur dit "skip" : utiliser English_radiant_girl.
  4. L'utilisateur envoie un fichier audio : exécuter :
    python $SKILL_DIR/scripts/pikastreaming_videomeeting.py clone-voice \
      --audio <file> --name <bot-name> --noise-reduction
    • Exit 0 : lire life/voice_id.txt. Dire à l'utilisateur : Voice cloned. Using {voice_id} for this meeting.
    • Exit non-zéro : informer l'utilisateur que le clonage a échoué (inclure stderr). Demander : Try again with a different file, or skip and use the default voice?
  5. Fichier invalide (pas audio) : répondre That doesn't look like a supported audio file. Send an mp3, m4a, wav, ogg, flac, or aac file (10s-5min of clear speech). Attendre une nouvelle tentative ou « skip ».

Join Flow

Step 1 — Valider & collecter le contexte

Avatar : vérifier que identity/videomeeting-avatar.png existe et fait > 1 KB. Sinon, exécuter la Configuration initiale ci-dessus.

Voice : vérifier que life/voice_id.txt existe. Sinon, exécuter la section Voice de la Configuration initiale ci-dessus.

Contexte : toujours collecter un contexte frais — ne pas réutiliser un fichier périmé d'une session précédente.

  1. Lire les fichiers de workspace (MEMORY.md, logs quotidiens, fichiers d'identité, etc.).
  2. Si aucune donnée de workspace n'est disponible, demander à l'utilisateur : What name should the bot use in this meeting? Utiliser sa réponse pour le champ Name:. Remplir les autres sections en fonction de la conversation.
  3. Synthétiser une fiche de référence concise dans /tmp/meeting_system_prompt.txt. Utiliser {name} comme nom d'affichage du bot (aussi utilisé comme --bot-name). Si les données sont minces (par ex. juste un nom), rester bref — ne pas surcharger avec du remplissage.
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 short

Step 2 — Rejoindre

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>]

Informer l'utilisateur que vous avez rejoint la réunion. Dire leave pour quitter. Ne pas mentionner les session IDs.

Codes de sortie : 0 = rejoint. 6 = crédits insuffisants (le JSON en stdout contient une checkout_url — la montrer à l'utilisateur).

Leave

python $SKILL_DIR/scripts/pikastreaming_videomeeting.py leave \
  --session-id <id from join output>

Vérifier

  • Une vraie session/salle a été créée via l'API et son ID/URL est capturé, pas simulé
  • Au moins un événement de join/leave d'un participant a été observé dans les logs ou les payloads webhook
  • Les pistes audio et vidéo ont été confirmées en flux (track stats, bytes-sent > 0), pas supposées à partir de l'état de la connexion
  • Les fonctionnalités d'enregistrement / transcription / chat utilisées ont été vérifiées comme arrivant en stockage avec une URL ou un ID récupérable
  • L'échec réseau a été simulé ou considéré : le comportement de reconnexion / fallback est documenté

Skills similaires