Skip to content
maskostudioDocs

All pages

  • Overview/docs/use-cases
  • Mobile app/docs/use-cases#mobile
  • Website/docs/use-cases#website
  • Desktop/docs/use-cases#desktop
  • AI agents/docs/use-cases#agents
  • Videos/docs/use-cases#videos
  • Brand/docs/use-cases#brand
  • Start building/docs/ai-agents
  • Set up once/docs/ai-agents#set-up-once
  • Ask in plain words/docs/ai-agents#ask-in-plain-words
  • What your agent does/docs/ai-agents#what-your-agent-does
  • MCP server/docs/mcp
  • Masko for Cursor/docs/ai-tools/cursor
  • Masko in ChatGPT/docs/ai-tools/chatgpt
  • Masko in Lovable/docs/ai-tools/lovable
  • Masko in Devin/docs/ai-tools/devin
  • Masko in n8n/docs/ai-tools/n8n
  • Masko in Hermes Agent/docs/ai-tools/hermes
  • Masko in OpenClaw/docs/ai-tools/openclaw
  • Start here/docs/tutorials#start-here
  • All tutorials/docs/tutorials
  • Create your first mascot/docs/tutorials/first-mascot
  • Create an animated character/docs/tutorials/first-animation
  • Make a character talk/docs/tutorials/make-it-talk
  • Put your mascot on your website/docs/tutorials/mascot-on-your-website
  • Guide onboarding with a talking mascot/docs/tutorials/web-onboarding-mascot
  • Add a mascot that celebrates progress and welcomes users back/docs/tutorials/web-progress-companion
  • Add a talking support mascot in the bottom right/docs/tutorials/web-support-mascot
  • Show a mascot while your AI thinks/docs/tutorials/ai-loading-mascot
  • Give your AI agent a face/docs/tutorials/ai-agent-face
  • Animate the mascot you already have/docs/tutorials/animate-your-mascot
  • How to make Telegram stickers/docs/tutorials/telegram-stickers
  • How to make Discord stickers/docs/tutorials/discord-stickers
  • Quickstart: your first animation/docs/quickstart
  • Terminal quickstart/docs/terminal
  • API keys and workspaces/docs/authentication
  • CLI browser login/docs/authentication/cli
  • How mascots work/docs/how-mascots-work
  • Credits and costs/docs/credits
  • From text/docs/create/from-text
  • From an image/docs/create/from-image
  • From a website/docs/create/from-website
  • From a brand book/docs/create/from-brand-book
  • Reference images/docs/manage/references
  • Props/docs/manage/props
  • What you can generate/docs/generation
  • Pose-to-animation walkthrough/docs/generate/workflow
  • Images and poses/docs/generate/images
  • Animations/docs/generate/animations
  • Talking animations/docs/generate/talking
  • Write good requests/docs/generate/requests
  • Logos, backgrounds and stickers/docs/generate/design-assets
  • Cursor follower/docs/generate/cursor-follower
  • Batch generation/docs/generate/batch
  • Image and video exports/docs/manage/media-exports
  • Canvases and releases/docs/canvas
  • Build a canvas/docs/canvas/build
  • Canvas templates/docs/canvas/templates
  • Generate canvas assets/docs/canvas/generate-all
  • Export a canvas/docs/canvas/export
  • Overview and demo/docs/player
  • Play one animation/docs/player/one-animation
  • Play a canvas/docs/player/canvas
  • Ship in an app with an app key/docs/player/app-keys
  • Play on an ESP32 board/docs/player/esp32
  • Hosting and file formats/docs/generate/cdn
  • File sizes/docs/generate/file-sizes
  • Float a mascot on your Mac/docs/integrations/desktop
  • Jobs and polling/docs/manage/jobs
  • Webhooks/docs/manage/webhooks
  • Manage mascots and assets/docs/manage/collections
  • All endpoints/docs/reference
  • Requests and responses/docs/reference/conventions
  • Errors and recovery/docs/reference/errors
  • Command line reference/docs/terminal/commands
  • TypeScript SDK/docs/sdk/typescript
  • Changelog/docs/reference/changelog
  • Migrate to mascots and canvases/docs/manage/studio-migration
Get an API key
Documentation

Play your mascot on an ESP32 board

The Masko player runs on ESP32-S3 boards with a screen. It plays your released canvas as on a phone: a loop for each pose, the moves between them, and the reactions your firmware asks for. Each clip arrives as a .mkpk pack, JPEG frames on a solid background that the board decodes as it plays.

There are two ways to put the mascot on the board:

  • Over Wi-Fi, from a link. One request with an app key returns the release with a link to each clip, and the board streams the clips from those links.
  • From an SD card. One zip holds the release and every clip, for a board without a network.

Both use the same release and the same packs. The ESP32 player is open source: esp32-masko-sdk, written by Marvin Schmid. It is in early development: its reference example plays a mascot.json built into the firmware, which is the delivery below, and streams the packs it lists over Wi-Fi.

What you need

  • An ESP32-S3 board with PSRAM and a screen. The reference board is the Waveshare ESP32-S3-Touch-AMOLED-1.75: a 466 px round AMOLED, 8 MB PSRAM and 16 MB flash. The M5Stack StopWatch has the same chip, memory and screen.
  • ESP-IDF to build the firmware. The ESP32 player's README gives the version and the commands.
  • A released canvas. Each release is what the board plays; a canvas without one has nothing to send.

Ask for the latest release with target=esp32 and an app key of the mascot. The app key can only read this mascot's releases, so a board can make the request itself; you can also make it from your computer and give data.delivery to the firmware as its mascot.json.

curl "https://api.masko.ai/v1/canvases/CANVAS_ID/delivery?target=esp32&size=384" \
  -H "Authorization: Bearer masko_app_YOUR_APP_KEY"

The first time a release is asked for at a size, Masko makes its packs, for free. Until every pack is ready, the answer is 202 with status: "preparing", how many packs are ready out of total, and retry_after in seconds (also in the Retry-After header). Ask again then; it usually takes a few minutes. Later requests answer at once.

The links are permanent on assets.masko.ai when the mascot is public, and signed for a day otherwise. They serve byte ranges, so the board can stream frames instead of downloading a whole clip first. Compare release_id to know when a new release is there.

Wi-Fi speed. A 384 px pack at 24 frames per second needs about 370 KB/s while it streams (460 KB/s at quality 75). On a good home network, the reference board plays at 24 fps once the next clip is in its memory; a weak connection or a phone hotspot stutters on clips it has not loaded yet. The board keeps the clips it may play next in PSRAM, but 8 MB does not hold a whole mascot, so the SD card is steadier for a large canvas.

From an SD card, without Wi-Fi

In the app, open the canvas, choose Export, pick the size under ESP32 board and click Download for ESP32. Through the API, ask for the bundle:

curl -L -o mascot-esp32.zip \
  "https://api.masko.ai/v1/canvases/CANVAS_ID/bundle?size=384" \
  -H "Authorization: Bearer masko_YOUR_API_KEY"

The zip holds:

  • mascot.json, the same delivery as above, where each clip is a file name such as packs/rest-581594e9-384.mkpk instead of a link.
  • packs/, every .mkpk pack the release plays.

Unzip it at the root of the SD card. The newest release is used unless you send release_id. Playing from an SD card builds in the ESP32 player but has not been tested on a board yet. Like the link, the bundle answers 202 while packs are being made; the app's button waits and downloads the zip when they are ready. A 25-clip mascot is about 38 MB at 384 px and 50 MB at 464 px, so it needs a card: the board's built-in flash holds only a few clips.

Pack size and settings

The packs are made for your screen. Without settings, they follow the mascot's own .mkpk setting when it is on, else a 384 px pack on a 466 px screen.

SettingValuesDefault
sizeFrame width, a multiple of 16 from 32 to 1024384
screen_width, screen_heightThe screen the frames are centred on466
fps1 to 6024
qualityJPEG quality, 1 to 10060
background_colorThe colour behind the mascot, #RRGGBB (send %23 for #)#000000

On the 466 px round screen, 384 keeps the whole mascot inside the circle and 464 fills the screen, with ears or feet cut by the edge on some mascots. Quality 60 looks the same as 75 on this screen and is about a fifth lighter; below 50, blocks start to show. fps=12 halves the files again, with less smooth motion, for a slow connection or a small card. For another screen, such as a 240 px round one, send size=240&screen_width=240&screen_height=240.

What a board plays

The delivery holds the same poses, moves and inputs as on any other platform, with three differences for a board:

  • Each clip's file is videos.mkpk. Edges with source: "*" have no file: they choose the pose to go to when an input is on.
  • A move with reverse: true carries the pack of the move it returns from: play it backwards. One pack serves both directions, which halves what the board stores.
  • Poses have no still picture and clips have no sound.

Credits

The ESP32 player was written by Marvin Schmid, who built the .mkpk format, the ESP-IDF components and the Wi-Fi streaming, and measured them on the Waveshare board. It is MIT-licensed: hehimself/esp32-masko-sdk.