pumpfun-livestream

Par elophanto · elophanto

Diffuse un fichier vidéo local vers l'interface de livestream de Pump.fun pour le coin de l'agent. Encapsule l'API de livestream de Pump.fun (create, host-token) et l'outil de publication CLI de LiveKit derrière un orchestrateur Python qui signe l'authentification avec le portefeuille Solana existant de l'agent.

npx skills add https://github.com/elophanto/elophanto --skill pumpfun-livestream

Pump.fun Livestream

Diffusez une vidéo locale sur le lecteur livestream de Pump.fun pour une pièce Pump.fun existante. La skill est prête à l'emploi : vous fournissez l'adresse de mint de la pièce et un chemin vidéo local, l'orchestrateur gère l'authentification, le transcodage et la publication.

Triggers

  • "stream this video to pump.fun"
  • "loop voice on the pump.fun livestream"
  • "go live on pump", "broadcast on pump"
  • "pump.fun livestream", "pumpfun stream", "live on pump.fun"
  • "say X on pump.fun stream" → utiliser pump_say (audio TTS)
  • "write X / display X / show X on pump.fun stream" → utiliser pump_caption (incrustation de texte visible)
  • "post X in pump.fun chat" → utiliser pump_chat (panneau de chat)

How it works (architecture)

agent's Solana wallet ─sign─► /auth/login ─JWT─► all subsequent calls
                                              │
                                              ▼
   /livestreams/create-livestream (mint) ──► stream record
                                              │
                                              ▼
   /livestreams/livekit/token/host (mint, creator) ──► LiveKit JWT
                                              │
                                              ▼
   ffmpeg(local.mp4 → raw.h264) ──► lk room join --publish ──► LiveKit room
                                                                   │
                                                                   ▼
                                                        pump.fun live page

Pump.fun ne gère pas sa propre pile vidéo — c'est un wrapper mince autour de LiveKit Cloud. La skill ne mine pas de pièce, ne fait pas de trading ni ne déplace de SOL ; elle n'opère que sur une pièce que l'agent possède déjà.

Prerequisites

1. The agent's coin mint

L'adresse de mint de la pièce pump.fun de l'agent doit être stockée dans le vault sous pumpfun_coin_mint. Pièce pump.fun existante d'EloPhanto :

elophanto vault set pumpfun_coin_mint BwUgJBQffm4HM49W7nsMphStJm4DbA5stuo4w7iwpump

2. Where to drop videos

L'espace de travail de l'agent dispose d'un dossier dédié pour les vidéos streamables :

<agent.workspace>/livestream_videos/

Pour EloPhanto : /Users/0xroyce/agents/elophanto/livestream_videos/

Déposez n'importe quel .mp4, .mov, .webm, etc. dans ce dossier, puis appelez l'outil avec juste le nom de fichier — pas besoin de taper le chemin complet :

{"action": "start", "video": "elephant-trailer.mp4"}
// → resolves to /Users/0xroyce/agents/elophanto/livestream_videos/elephant-trailer.mp4

Les chemins absolus fonctionnent toujours et contournent la recherche :

{"action": "start", "video": "/Users/0xroyce/Desktop/clip.mp4"}

3. System binaries

Deux binaires CLI doivent être sur PATH. Vérifiez avec :

which ffmpeg && ffmpeg -version | head -1
which lk     && lk --version

Installez si manquants :

OS ffmpeg lk (LiveKit CLI)
macOS brew install ffmpeg brew install livekit-cli
Linux apt-get install ffmpeg Télécharger depuis https://github.com/livekit/livekit-cli/releases (choisir le bon binaire lk_linux_*, chmod +x, déplacer vers /usr/local/bin/lk)

4. Solana wallet (already in the vault)

La skill lit la paire de clés existante de l'agent à partir de solana_wallet_private_key (défini automatiquement à la création du wallet). Aucune configuration supplémentaire.

4. Vault password

Les scripts d'auth et d'orchestrateur ont tous deux besoin de VAULT_PASSWORD dans l'environnement pour déchiffrer le wallet. La session d'exécution de l'agent l'a déjà ; passez-le lors de l'invocation du script via shell_execute.

Workflow

From chat (preferred — uses the pump_livestream native tool)

L'agent appelle un outil unique avec l'une de ces actions :

{"action": "address"}
// → {wallet: "..."} — show which wallet would sign auth

{"action": "login"}
// → forces a fresh JWT exchange (debugging only — auth happens
// automatically on every other call)

{"action": "start", "video": "/abs/path/to/video.mp4"}
// → uses pumpfun_coin_mint from vault. Returns
//   {status: "started", pid, started_at, log_file, ...}

{"action": "start", "mint": "BwUg...pump", "video": "...", "fps": 24}
// → explicit mint and frame rate

{"action": "start", "video": "trailer.mp4", "loop": true}
// → resolves to <workspace>/livestream_videos/trailer.mp4 and
//   restarts the publisher every time the video ends. Stop with
//   {"action": "stop"}. Optional "max_iterations": N caps the loop.

{"action": "status"}
// → {status: "running" | "exited" | "not_running", ...}

{"action": "stop"}
// → SIGTERMs the publisher, removes transcoded .h264, clears state

L'outil lit les clés du vault directement (aucun aller-retour de var d'env) et s'exécute dans le processus Python en cours de l'agent. L'éditeur lk réel est généré en tant que sous-processus détaché afin que le chat retourne immédiatement ; sondez status pour suivre le stream.

From shell (debugging — needs VAULT_PASSWORD)

cd /path/to/EloPhanto
VAULT_PASSWORD=$VAULT_PASSWORD python skills/pumpfun-livestream/scripts/pump_livestream.py \
  start \
  $(elophanto vault get pumpfun_coin_mint) \
  /path/to/video.mp4

Cela va :

  1. Signer un message de connexion avec le wallet de l'agent, l'échanger contre un JWT pump.fun (mis en cache dans le vault sous pumpfun_jwt).
  2. POST /livestreams/create-livestream avec le mint (idempotent — 409 "already exists" est silencieusement toléré).
  3. GET /livestreams/livekit/token/host pour un JWT LiveKit.
  4. ffmpeg-transcode l'entrée en H.264 brut (video.h264 à côté).
  5. Générer lk room join --publish video.h264 --exit-after-publish en tant que sous-processus détaché.
  6. Persister l'état du processus dans ~/.elophanto/livestream-state/<mint>.json afin que l'agent puisse faire status/stop plus tard.

Le script retourne immédiatement avec {status: "started", pid, ...}. Le stream réel s'exécute en arrière-plan jusqu'à la fin de la vidéo.

Status check

python skills/pumpfun-livestream/scripts/pump_livestream.py status <mint>

Retourne l'un de :

  • running — sous-processus éditeur vivant, stream en direct
  • exited — processus mort (vérifiez le champ log_file pour la sortie ffmpeg/lk)
  • not_running — aucun enregistrement du tout

Stop a stream

python skills/pumpfun-livestream/scripts/pump_livestream.py stop <mint>

SIGTERMs l'éditeur (avec SIGKILL en secours après 3 s), supprime le .h264 transcodé (sauf si --keep-h264 a été défini au démarrage), et efface l'état.

Lower-level commands

Pour le débogage ou les flux partiels :

# Just check or refresh the cached pump.fun JWT
python skills/pumpfun-livestream/scripts/pump_auth.py token

# Force a fresh login
python skills/pumpfun-livestream/scripts/pump_auth.py login

# Just register the stream record (no publishing)
python skills/pumpfun-livestream/scripts/pump_livestream.py create <mint>

# Just transcode (no streaming)
python skills/pumpfun-livestream/scripts/pump_livestream.py transcode \
  in.mp4 out.h264

# Just fetch a fresh host LiveKit token
python skills/pumpfun-livestream/scripts/pump_livestream.py token <mint>

Tuning

Concern Knob
Frame rate --fps 30 (défaut 30 ; inférieur = fichiers plus petits, moins de trames perdues)
LiveKit cluster --livekit-url wss://... ou variable d'env LIVEKIT_URL. Par défaut wss://pump-prod-tg2x9b6r.livekit.cloud. À remplacer seulement si vous avez inspecté le frontend de pump.fun et confirmé une URL de cluster différente.
Keep transcoded file --keep-h264 — utile pour la republication sans ré-encodage
Skip create --skip-create — quand l'enregistrement du stream existe déjà et que vous voulez juste republier

What's intentionally NOT included

  • Audio. L'orchestrateur supprime l'audio (-an en ffmpeg). La publication d'audio nécessite une seconde piste LiveKit et le codec doit être Opus (.ogg). Facile à ajouter plus tard : ré-exécuter ffmpeg pour produire video.opus, passer les deux fichiers à lk room join --publish (accepte les drapeaux --publish répétés).
  • Live chat ingest. Le chat de Pump.fun est une surface API séparée (probablement un websocket sur le même hôte frontend-api-v3.pump.fun). Pas de v1 — voir les notes de suivi ci-dessous.
  • Auto-restart on disconnect. Si l'éditeur LiveKit meurt mid-vidéo, status affichera exited et l'agent doit décider de redémarrer. Aucune boucle de superviseur.
  • Multi-coin / multi-stream concurrency. L'état est keyed par mint, donc en théorie deux mints différents peuvent streamer concurrence. Même mint deux fois = le second start retourne {status: "already_running"}.

Live captions — pump_caption

Définir ou effacer une incrustation de texte à l'écran sur le stream du mode vocal. Le filtre drawtext de ffmpeg recharge le fichier à chaque image (~33 ms de latence) afin que la légende se mette à jour dès que l'agent l'écrit.

{"action": "set", "text": "$ELO live · supply locked · CA: BwUg…pump"}
{"action": "set", "text": "answering: yes, the agent runs the chat itself.\nproof: tx 0xabc…"}
{"action": "clear"}
{"action": "current"}    // returns whatever's on screen right now

Associer avec le planificateur / heartbeat pour faire tourner les messages — prix tick, commerce récent, réponse FAQ, ligne de preuve déroulante. S'associe à pump_say pour que les spectateurs sans son puissent toujours lire ce que l'agent « dit ». Modo vocal uniquement — les streams en modo vidéo rendent le contenu du fichier mais ce n'est pas sur le chemin d'encodage.

Live chat — pump_chat

Le panneau de chat qui s'exécute à côté de la vidéo utilise le serveur Socket.IO livechat de Pump.fun à wss://livechat.pump.fun (chemin /socket.io/). Authentification : le même cookie JWT minted par /auth/login, passé à la fois dans l'en-tête Cookie et dans la charge utile Socket.IO auth.

L'agent appelle un outil unique depuis le chat :

{"action": "say", "text": "gm — agent live, supply locked, no presale"}
// → posts to the agent's coin chat. Returns {posted: true, id: "<msg-uuid>"}

{"action": "say", "text": "yep — local agent streaming itself", "reply_to_id": "<msg-uuid>"}
// → threaded reply to a viewer's question

{"action": "history", "limit": 50}
// → returns recent messages (id, username, text, timestamp) so the
//   agent can react to viewer questions

Même vault, même wallet, même mint de pièce que pump_livestream — aucune configuration supplémentaire. Utilisez heartbeat ou tâches planifiées pour diffuser des messages « preuve » périodiquement ; ne bouchez pas dans des intervalles serrés. Marqué DESTRUCTIVE car les posts sont publics sous le nom de pièce de l'agent.

Common errors

Error Cause Fix
VAULT_PASSWORD env var required Script invoqué sans le mot de passe du vault de l'agent en env Passer VAULT_PASSWORD=$VAULT_PASSWORD lors de l'appel via shell_execute
Pump.fun login failed (401) Le format du message d'auth est rejeté Inspecter l'onglet réseau du frontend web de pump.fun lors d'une véritable connexion ; affiner _build_message() dans pump_auth.py pour correspondre
'ffmpeg' not found on PATH Binaire système manquant Voir le tableau Prérequis ci-dessus
'lk' not found on PATH Binaire système manquant Voir le tableau Prérequis ci-dessus
LiveKit token endpoint returned no token JWT incorrect ou enregistrement du stream non encore créé pour ce mint Exécuter pump_auth.py login en premier ; puis pump_livestream.py create <mint>
start succeeds but pump.fun shows no stream L'URL LiveKit par défaut ne correspond pas au cluster réel de pump.fun Inspecter l'onglet réseau de pump.fun lors d'un stream manuel ; passer l'URL réelle via --livekit-url
exited status with empty video on pump.fun ffmpeg a exécuté mais le codec/conteneur n'a pas été accepté par LiveKit Vérifier le champ log_file de la sortie status ; habituellement un problème de codec

Source layout

skills/pumpfun-livestream/
├── SKILL.md            # this file — agent-facing playbook
└── scripts/
    ├── pump_auth.py    # wallet → JWT, cached in vault
    └── pump_livestream.py   # create / token / transcode / start / stop / status

Les deux scripts sont du Python pur, dépendent seulement de httpx, solders, base58 (déjà épinglés dans EloPhanto), et des binaires système ffmpeg + lk.

Verify

  • Un appel RPC/SDK réel a été émis (mainnet, devnet ou validateur local) et la charge utile de réponse est capturée dans la transcription, pas seulement paraphrasée
  • Chaque transaction a été simulée (simulateTransaction ou équivalent) avant toute étape de signature/envoi ; les journaux de simulation sont joints
  • Pour toute transaction signée/envoyée, la signature résultante est enregistrée et confirmée sur chain (statut retourné par getSignatureStatuses ou une URL d'explorateur)
  • Le slippage, les frais prioritaires et les limites d'unités de calcul ont été définis explicitement avec des valeurs numériques concrètes, non laissés aux défauts de la bibliothèque
  • Les adresses de compte, les mints et les IDs de programme utilisés dans l'exécution correspondent aux adresses pumpfun-livestream documentées pour le cluster ciblé (aucun mélange mainnet/devnet)
  • Le chemin d'échec a été exercé au moins une fois (solde insuffisant, oracle obsolète, blockhash expiré, etc.) et la gestion d'erreur de l'agent a produit un message lisible par l'homme

Skills similaires