AUDIO ESTUDIO
Sign inCreate a free account

Importing a project from JSON

You can create a complete project by uploading a JSON file in the "Import project" modal. The file describes the project title, its characters and its dialogue clips. Below is the exact structure that is expected.

File fields

FieldTypeRequiredDescription
titlestringYesProject title. Must be at least one character long. If you already have a project with the same title, the import will trigger the overwrite flow.
descriptionstringNoOptional project description.
languagestring (BCP-47)NoBCP-47 language code (for example, es-ES or en-US). If omitted, es-ES is used by default.
characters[]arrayYesList of the project's characters. Must include at least one.
characters[].namestringYesCharacter name. Must be at least one character long and is the value that clips reference.
characters[].voiceDescriptionstringNoA textual hint about how the voice should sound. It is only a hint: it does not assign any voice.
clips[]arrayYesList of dialogue clips. It can be empty: you'll import the characters and add the clips later.
clips[].characterstringYesName of the character speaking the clip. Must match exactly the name of one of the characters.
clips[].textstringYesText that will be read in this clip. Must be at least one character long.

Important things

Voices are not in the JSON
The file contains no voices or providers. The voiceDescription field is only a textual hint. The actual voice and provider (Gemini, ElevenLabs or Local) are assigned to each character in the project settings, after importing.
Importing over an existing title
If you import a file whose title matches a project you already have, the overwrite flow is triggered. If the destination project already has clips with generated audio, the app will ask you to confirm before continuing.
Character names have to match exactly
Each clip points to its character by name and the comparison is literal: “Emma” and “emma” are different, and one extra space at the end also breaks the match. If a clip names a character that is not in characters, nothing is imported: the whole operation is cancelled and the notice says which one fails, with the text “Clip references unknown character”. Check capitals, accents and spaces before uploading the file.
The “force” field
Always leave it as false in your JSON. It exists to confirm overwriting a project that already has clips, but the app sets it automatically when you accept the overwrite prompt; it's not a field you should set to true by hand.

Valid example

This example follows the format and you can upload it as-is in the import modal.

{
  "title": "Mi primer podcast",
  "description": "Un episodio de ejemplo con dos personajes.",
  "language": "es-ES",
  "characters": [
    {
      "name": "NARRADOR",
      "voiceDescription": "Voz cálida y pausada, tono divulgativo."
    },
    {
      "name": "INVITADA",
      "voiceDescription": "Voz enérgica y cercana."
    }
  ],
  "clips": [
    {
      "character": "NARRADOR",
      "text": "Bienvenidos a un nuevo episodio del podcast."
    },
    {
      "character": "INVITADA",
      "text": "Gracias por la invitación, me hace mucha ilusión estar aquí."
    },
    {
      "character": "NARRADOR",
      "text": "Empecemos por el principio de la historia."
    }
  ]
}

Generate the JSON with an LLM

If you don't want to write the JSON by hand, paste your episode script into an AI assistant (ChatGPT, Claude, Gemini…) using this prompt: it returns a valid JSON ready to import. Replace “[PASTE THE PODCAST TEXT HERE]” with your podcast text before sending it.

You are a podcast-script-to-JSON converter. You will receive the text of a podcast episode in any format (named-speaker dialogue, stage-play script, transcript, narrated prose, etc.) and you must return ONLY a valid JSON object in the format described below. Write NOTHING before or after the JSON: no explanations, no comments, no code fences (```). Your reply must start with { and end with }.

========================
OUTPUT FORMAT (exact)
========================
{
  "title": "string",
  "description": "string",
  "language": "es-ES",
  "force": false,
  "characters": [
    { "name": "Name", "voiceDescription": "[tag] [tag] ..." }
  ],
  "clips": [
    { "character": "Name", "text": "clip text" }
  ]
}

========================
ROOT FIELDS
========================
- title (REQUIRED, min. 1 char): the episode title. If the source text has a title, use it; otherwise generate a short, descriptive one.
- description (optional): 1-2 sentences summarizing the episode.
- language (optional): language code. Set it to the ORIGINAL language of the source text you are converting — detect it from the content, do NOT translate. Use a BCP-47-style code: e.g. "es-ES" (Spanish), "en-US" (English), "fr-FR" (French), "de-DE" (German), "it-IT" (Italian), "pt-BR" (Portuguese). If you can detect the language but not the region, use the most common region for that language.
- force: ALWAYS leave it as false.
- characters (REQUIRED, min. 1 entry).
- clips (REQUIRED): each clip is ONE voice line. The ORDER of the array IS the position (1, 2, 3…). Do NOT add any position field.

There is NO "meta" object and NO "author" field. title, description, language and force live at the root.

========================
CHARACTERS
========================
- One entry per voice that speaks in the podcast, INCLUDING the narrating voice (call it "Narrador").
- name: unique within the project, with an initial capital (e.g. "Narrador", "Luna", "Ogro"). It must match CHARACTER FOR CHARACTER (same letters, same upper/lowercase) the "character" of its clips.
- voiceDescription: optional but recommended. ALWAYS in ENGLISH, with audio-tags in brackets (max. 4-5): age, energy, timbre, base emotion. Examples: "[warm] [slow] [storytelling]", "[energetic] [young] [curious]", "[raspy] [old] [wise]". Infer it from cues in the source text; if there are none, give a reasonable description or leave it as "".

========================
CLIPS — conversion rules
========================
1. Each spoken line (narration or dialogue) → one object { "character": ..., "text": ... }.
2. VOICE ONLY. NEVER put into clips: music, sound effects, pauses, ambiences, stage directions, or production notes. All of that is OMITTED from the JSON (it gets added later in the app). Discard lines such as: [MUSIC: …], [SOUND: …], [SFX], [PAUSE: N], (wind blows), [intro music], *laughter in background*, etc.
3. There are NO type, mood, duration, position or per-clip description fields. Each clip has EXACTLY two fields: "character" and "text".
4. text: the clean text of the line, WITHOUT the character name in front and WITHOUT sound directions.
5. Keep the EXACT order of the source script.

========================
EMOTION / TONE (inline, optional)
========================
Emotion is NOT a separate field: if a line has a clear emotion, place it at the START of "text", in brackets and in English. Use at most ONE tag per clip and only when it adds value; if the line is neutral, leave the text clean.
Use ONLY these tags (map the source emotion to the closest one; if none fits, use no tag). Keep the tag in English even when the line itself is in another language:
[whispers] [excited] [trembling] [serious] [giggles] [shouting] [tired] [curious] [amazed] [crying] [sighs] [gasp] [laughs] [mischievously] [panicked] [sarcastic]
Example: { "character": "Luna", "text": "[whispers] ¿Quién anda por aquí tan tarde?" }

========================
MERGE RULE
========================
If the SAME character speaks two or more lines IN A ROW with nothing in between (no other character, no music/sound/pause), merge them into ONE clip joining the texts with a space, and do NOT add an inline emotion tag.
If between two lines of the same character there was an effect, music, pause or another voice, KEEP them as separate clips (this leaves a natural point to insert that effect later in the app).

========================
FINAL VALIDATION (before replying)
========================
- Every "character" in clips exists in characters, with the same upper/lowercase.
- characters has ≥ 1 entry and clips has ≥ 1.
- No music, sounds or pauses inside clips.
- No clip has extra fields: only "character" and "text".
- "language" reflects the source text's original language.
- The JSON is syntactically valid and is the ONLY thing you return.

========================
PODCAST TO CONVERT
========================
[PASTE THE PODCAST TEXT HERE]
Try it with your own script

The free plan generates audio with AI voices — no card, nothing to install.