Skip to main content
This page covers every media command in Ravi: what each one needs, what it prints, and how its output reaches a conversation. At the end you will be able to generate audio and images, send any file into a chat, and read the files people send to your agent.

Before you start

Put API keys in ~/.ravi/.env (open it with ravi daemon env), then restart the daemon so it picks them up:
Install the system tools with brew install ffmpeg yt-dlp (macOS) or your Linux package manager. Two rules apply to every command below:
  • Generating is immediate. Delivering to a chat is not. Anything that posts into a conversation (--send, ravi media send, ravi stickers send) is a dry-run without --execute: it prints the plan and exits with code 3. Add --execute to send.
  • “The current chat” means the chat of the session that runs the command. When your agent runs --send while answering a Slack thread or a WhatsApp group, the file goes back there. From your own terminal there is no current chat, so use ravi media send with explicit --to and --account.
On Slack, files are uploaded natively through the Slack Web API into the same channel or thread. On WhatsApp (and other Omni channels), Ravi calls omni send and reports success only after Omni accepts the request.

Audio generation (text to speech)

Ravi turns text into speech with ElevenLabs.
The language defaults to Portuguese (pt-br). Pass --lang en for English, or set tts_lang in the agent defaults (see Defaults).
Output:
With --send, Ravi converts the MP3 to OGG/Opus (64 kbps, 48 kHz, mono) with ffmpeg and sends the .ogg. WhatsApp shows it as a voice note; Slack shows it as an audio file. If ffmpeg is missing or fails, the MP3 is sent as a regular audio file.

Transcription

Ravi transcribes audio with Whisper. It uses Groq when GROQ_API_KEY is set, otherwise OpenAI. There is no fallback between them: if the chosen provider fails, the transcription fails.
--lang defaults to pt. Supported formats: .ogg, .opus, .mp3, .m4a, .mp4, .wav, .webm. Audio longer than 10 minutes is split with ffmpeg into 10-minute chunks that overlap by 15 seconds, transcribed chunk by chunk and joined.

Voice messages your agent receives

Voice notes and audio files that arrive on Slack or WhatsApp are transcribed automatically, and the transcript goes into the agent’s prompt (see Files people send to your agent). This uses the same provider order, with Portuguese (pt) as the language hint. There is no setting to change that hint today; for audio in another language, transcribe the saved file again with ravi transcribe file <path> --lang <code>.

Image generation

Ravi generates and edits images with OpenAI or Gemini.

Choose a provider first

There is no built-in default provider. Without one, ravi image generate fails with IMAGE_PROVIDER_NOT_CONFIGURED. Set a global default once:
Ravi picks each value in this order: the command flag, the agent defaults, the instance defaults, the global setting (image.provider, image.model, image.mode, image.quality, image.format), then the environment (RAVI_IMAGE_PROVIDER, RAVI_IMAGE_MODEL). If the selected provider fails, the command fails; retry with another --provider yourself.

Generate

Generation is asynchronous by default. The command records an image artifact, starts a background worker and prints:
ravi artifacts show <id> gives the file path once the artifact is completed. When the command runs inside a session, that session is told when the image completes or fails, so the agent does not need to poll. With --sync, the command waits and prints the result:
When the command runs in a session that belongs to a chat, the image is always sent back to that chat when it is ready, even without --send. That is why your agent needs --execute there. ravi image generate has no target flags; to send an image anywhere else, generate it and use ravi media send.

Video analysis

ravi video analyze turns a YouTube URL or a local video into a Markdown file. With the default strategy (auto), YouTube videos use their subtitles through yt-dlp and fall back to Gemini when there are none. Local files always use Gemini.
The Gemini model is gemini-2.5-flash unless you set GEMINI_VIDEO_MODEL. The subtitles path does not need GEMINI_API_KEY. Local files (.mp4, .mpeg, .mpg, .mov, .avi, .flv, .webm, .wmv, .3gpp) are uploaded to the Gemini Files API. YouTube videos must be public. The Markdown file has the title, duration, strategy, transcript and chapters. When Gemini is used it also has a summary, topics and timestamped visual descriptions.

Send any file

ravi media send delivers an image, video, audio file or document and waits for the channel to accept it.
The type comes from the extension: .jpg, .jpeg, .png, .gif, .webp are images; .mp4, .mov, .avi, .mkv are videos; .mp3, .ogg, .wav, .m4a, .opus are audio; anything else (including .pdf) is sent as a document.

Stickers (WhatsApp)

Ravi keeps a sticker catalog at ~/.ravi/stickers/catalog.json. Only WhatsApp supports outbound stickers today. The agent never sees sticker files; when stickers are enabled for it, its prompt gets a short list of sticker IDs and when to use them.
stickers add also takes --channels <csv> (default whatsapp), --agents <csv> (default: all agents), --disabled and --overwrite. stickers send and stickers remove are dry-runs without --execute. Sending queues the sticker for the daemon to deliver. Stickers are opt-in per agent: set "stickers": {"enabled": true} in the agent defaults (next section).

Agent, instance and global defaults

Instead of passing flags every time, store defaults:
defaults replaces the whole JSON object, and the agent’s defaults also hold its runtime permissions (runtimePermissions). Writing ravi agents set main defaults '{"tts_lang":"en"}' would drop the agent’s permission profile. Read the current object first and write back the merged version:

Files people send to your agent

When a message with a file arrives on Slack or WhatsApp, Ravi downloads it into the agent’s working directory and puts the local path in the prompt, so the agent can open it with its tools.
  • Location: <agent cwd>/attachments/, for example ~/ravi/main/attachments/.
  • Name: {timestamp}-{messageId}.{ext}.
  • Size limit: 20 MB. A larger file, or one that fails to download, still appears in the prompt, but without a file path.
  • Audio: saved and transcribed (see Transcription).
The message body the agent sees for a WhatsApp image with a caption, and for a voice note:
The message body for Slack files:
  • Artifacts: every generated image is recorded there.
  • Skills: the first ravi audio, ravi image, ravi video or ravi stickers call in an agent session loads the matching skill.
  • Connect Slack and Connect WhatsApp: the channels media is delivered to.
  • Configuration: everything ~/.ravi/.env can hold.