AI Production · Internal studio product

Visual Identity for an AI Assistant: Generative Persona, Animation Without Video Models, Messenger Distribution

A living assistant face from a single still portrait: deterministic ffmpeg loops instead of video models, delivered to the messenger through the standard Bot API.

Client
Internal studio product
Timeline
2026
Role
Art direction, generative pipeline…
Status
Production: the pack is published and extended programmatically via addStickerToSet; the persona serves as the assistant's canonical face. A true facial-expression layer (image-to-video) is on the roadmap.
4
Emotional states in the pack
calm, glow, sway, tension — all from a single still portrait
≤256 KB
Video sticker weight
WEBM VP9 512×512, up to 3 seconds, no audio track — per the Telegram specification
0
Video-model calls in the production pipeline
animation runs on deterministic ffmpeg loops; i2v models are on the roadmap
3
Independent pipeline layers
generation, animation, distribution — coupled only by artifacts on disk, each runnable separately

Context

LLM assistants are becoming an everyday work tool, yet they almost always remain faceless: text in a chat, a synthesized voice, a default icon. For a product the user talks to dozens of times a day, that is a missed layer of trust and recognition. A persona — a face, body language, a set of emotional states — turns a utility into a counterpart.

The studio's ecosystem already ran its own assistant: a messenger control bridge, a voice desktop console, an agent backend. Missing was the visual layer — a canonical face present across channels and able to express state. The project ran as internal R&D aimed at productization: the same methodology transfers to client brands as virtual ambassadors, support personas and product mascots.

Objective

Three parts. First, a canonical face under locked art direction — dark-red noir, neon rain, red rim light, a 2:3 portrait — produced by a reproducible pipeline, not one-off prompts in a web UI. Second, bringing it to life: image-to-video models meant per-iteration cost, minutes of waiting and non-deterministic motion, so a controllable animation method with zero video-model calls was required.

Third, distribution. Telegram video stickers impose a strict specification — exactly 512×512, at most 3 seconds and 256 KB, VP9 in WEBM, no audio — and the pack had to be assembled and extended programmatically through the standard Bot API, with no manual work or third-party services.

Approach

Persona generation is code: a Python client for GPT-4o Image (via the kie API aggregator) runs the full submit/poll/download cycle, with the access key read from the studio's shared key vault rather than stored in the script. Two persona candidates were generated; the variant with digital red highlights was approved as canonical, the second kept as backup.

The key architectural decision was rejecting AI video in the animation layer. The living face is assembled from the still portrait by deterministic ffmpeg loops — zoompan with a sinusoidal trajectory for breathing and sway, eq for a light pulse. That yields zero marginal cost per iteration, full control over duration and weight, and absolute reproducibility. Publication uses only the documented Bot API: createNewStickerSet with InputSticker format=video, multipart upload via attach://, extension via addStickerToSet.

Architecture

Three independent layers — generative, animation, distribution — are connected only by artifacts on disk. Each runs separately: regenerate the face without rebuilding animations, rebuild one loop without recreating the pack. The generative layer polls the aggregator's asynchronous queue and requests the portrait at 2:3 with compositional headroom for the square sticker crop.

The animation layer maps each emotional state to its own filter recipe — calm as a slow sinusoidal breath, glow as a brightness pulse, sway as horizontal motion, tension as a sharper combination of both. All four encode uniformly to WEBM VP9 512×512 under 3 seconds, audio stripped with -an, parameters tuned so every file clears the 256 KB limit.

Engineering decisions

Loop seamlessness is the quality bar: any jump between last and first frames destroys the illusion. The sinusoidal zoompan trajectories solve it mathematically — over the clip's duration the function completes a whole number of periods and returns the frame exactly to its start, so the cycle is continuous under infinite repetition. The 256 KB budget is cleared by the content's nature: inter-frame differences in a still-image loop are minimal and VP9 encodes them efficiently, with parameters tuned for the most dynamic state.

Integration reliability came from two diagnosed contracts: the aggregator silently rejects requests without a User-Agent header, so the client sets it on every call; and the Bot API requires files in the sticker JSON to be addressed via attach:// references in the multipart body — the non-obvious rule most homegrown sticker integrations break on.

Outcome

In production: a published animated sticker pack of four emotional states, conforming to the platform specification and extended programmatically. The persona is locked in as the assistant's canonical visual asset. More importantly, the identity became code: reference portrait, animation recipes and publication wrapper live in one project, and any change travels the same reproducible route — generate, loop, publish.

The economics validated the architecture: one emotional state is a single local ffmpeg run at zero compute cost, and generative spend arises only when creating new faces; determinism makes rebuilds byte-for-byte reproducible. On the roadmap: a true facial-expression layer via image-to-video models, an extended emotional palette generated from the canonical face, and event-driven delivery through the assistant's messenger bridge.

What we built

  • Generative persona client

    A full-cycle submit/poll/download Python script for GPT-4o Image via an API aggregator: sending the brief, polling the asynchronous task, downloading the 2:3 portrait into the asset structure. The access key is read from the studio's shared key vault.

  • Art direction and selection

    A locked visual code — dark-red noir, neon rain, red rim light. Two persona candidates generated; the variant with digital red highlights approved as canonical, the second kept as a backup.

  • ffmpeg animation recipes

    Four emotional states as filter recipes: sinusoidal "breathing" and sway via zoompan, light pulse via eq. Seamless loops without a single video-model call.

  • Encoding to the Telegram specification

    A single output profile: WEBM VP9 512×512, up to 3 seconds, up to 256 KB, audio track stripped with -an. Parameters tuned for the most dynamic state.

  • Programmatic pack publication

    Set creation via createNewStickerSet with InputSticker format=video: multipart file upload and addressing via attach:// in the sticker JSON description.

  • Incremental extension

    Growing the emotional palette without recreating the set — each new state is added with a separate addStickerToSet call.

  • Key-infrastructure integration

    Generative-pipeline credentials are not duplicated across projects: the client reads the key from the studio infrastructure's shared vault, common to all internal systems.

Engineering challenges

Liveliness without video models

Image-to-video generation would have meant non-deterministic motion and a cost per iteration. The answer: mathematically seamless ffmpeg loops — sinusoidal zoompan trajectories return the frame to its starting point, so the cycle is visually continuous.

Hard platform limits

The Telegram video-sticker specification: 512×512, ≤3 s, ≤256 KB, no audio. VP9 parameters were tuned for the worst-case dynamics, so the whole set clears the limit with margin thanks to the loop's minimal inter-frame differences.

Silent aggregator rejections

The API aggregator rejected requests without a User-Agent header without stating a reason. After diagnosis, the header was baked into the client as mandatory on every call; asynchronous status polling survives long generation queues.

The sticker multipart-upload contract

The Bot API requires addressing files from the InputSticker JSON description via the attach:// scheme in multipart transfers — a non-obvious requirement, worked out in the publication and extension wrapper.