Esquema de treino

Última atualização: 2026-05-29

Your Trainer é um aplicativo de ciclismo indoor para vários ciclistas em tablets Android. Controle do smart trainer com dados locais + controle local. Compra única.

O arquivo de treino .ytw é JSON puro — escreva-o em qualquer editor de texto, importe pela folha de compartilhamento, compartilhe com amigos. O editor visual cobre os casos comuns; o esquema é a saída de emergência quando você precisa de controle total.

Quando escrever à mão

A maioria dos ciclistas nunca precisa desta página — o editor visual de treinos e o AI Workout Coach cobrem tudo, de uma sessão de Limiar 4×8 a uma pilha de microbursts. Recorra ao esquema quando:

Exemplo mínimo

O menor arquivo .ytw válido é um programa com um Intervalo. Salve com a extensão .ytw e compartilhe para dentro do Your Trainer.

{
  "programId": "my-sweet-spot",
  "programName": "My Sweet Spot 30",
  "description": "A short sweet-spot workout.",
  "totalDuration": 1800,
  "workoutType": "POWER",
  "primaryLocale": "en",
  "intervals": [
    { "id": "warmup",   "duration": 300,  "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Warmup",     "intervalType": "WARMUP"   },
    { "id": "work",     "duration": 1200, "targetPowerPercent": 88, "intensityZone": "Z3", "label": "Sweet Spot", "intervalType": "INTERVAL" },
    { "id": "cooldown", "duration": 300,  "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Cooldown",   "intervalType": "COOLDOWN" }
  ]
}

Campos de nível superior

O objeto de nível superior descreve um programa de treino. Os campos obrigatórios estão sinalizados.

CampoTipoDescrição
programId obrigatóriostringIdentificador estável. Use kebab-case (my-sweet-spot). A chave única do treino na sua biblioteca — reimportar um arquivo com o mesmo programId atualiza a entrada existente em vez de criar uma duplicata.
programName obrigatóriostringNome de exibição no locale primário do ciclista.
description obrigatóriostringDescrição de uma ou duas frases mostrada no card do treino.
totalDuration obrigatóriointeiro (segundos)Duração total do treino. O app recalcula esse valor a partir dos Intervalos ao salvar, então é seguro deixá-lo inconsistente durante a autoria.
intervals obrigatórioarrayLista ordenada de objetos de Intervalo ou grupos de repetição.
workoutTypestringFamília do treino: POWER (padrão), HR_ZONE ou ROUTE. Veja Tipos de treino.
variantstringSubformato dentro da família: STANDARD (padrão) ou RAMP_TEST.
primaryLocalestring (BCP-47)Locale em que as strings foram escritas. Padrão "en". Define a cadeia de fallback entre locales.
categorystringCategorização em texto livre (ex.: "threshold", "endurance"). Opcional.
difficultyinteiro (1–5)Dificuldade subjetiva. Aparece no card do treino.
isUserCreatedbooleanTrue para treinos criados no app pelo ciclista; false para treinos importados / incluídos. Padrão false.
isFavoritebooleanSinalizador de fixar no topo. Os ciclistas alternam isso no app; normalmente omitido em arquivos compartilhados.
routeProfilearray de { distanceMeters, elevationMeters }Perfil completo de elevação para treinos ROUTE. Null para POWER e HR_ZONE.
stringsobject (locale → LocaleStrings)Traduções por locale do nome, descrição, rótulos de Intervalos e avisos.

Campos de Intervalo

Cada objeto de Intervalo descreve um bloco do treino. A forma do bloco depende do workoutType do pai — blocos de Potência usam percentuais de potência, blocos de Zona de FC usam um alvo de Zona.

CampoTipoDescrição
duration obrigatóriointeiro (segundos)Duração do bloco em segundos.
targetPowerPercent obrigatório para potênciainteiro (% do FTP)Alvo de potência para treinos POWER. Mutuamente exclusivo com targetHrZone.
targetPowerEndPercentinteiro (% do FTP)Potência final opcional para rampas. Quando presente, a wattagem-alvo interpola linearmente de targetPowerPercenttargetPowerEndPercent ao longo do bloco.
targetHrZone obrigatório para FCinteiro (1–5)Zona de FC para treinos HR_ZONE. Mutuamente exclusivo com targetPowerPercent.
intensityZone obrigatóriostringToken visual de Zona: Z1Z5. Define a cor na visualização do terreno. Veja Zonas de treino.
intervalTypestringWARMUP, COOLDOWN ou INTERVAL (padrão). Blocos de Aquecimento e Desaquecimento são excluídos dos resumos que consideram apenas o trabalho (potência média dos blocos de trabalho, tempo em Zona da parte de trabalho, etc.).
label obrigatóriostringTexto exibido no bloco no locale primário do ciclista. Variantes entre locales ficam em strings.<locale>.labels.
idstringSlug estável — a chave usada em strings.<locale>.labels e na composição da chave de avisos. Recomendado para qualquer treino que seja distribuído com traduções.
autoLabelbooleanTrue quando o rótulo foi gerado por um preset do editor em vez de digitado pelo ciclista. Rótulos automáticos são localizados pelo próprio Your Trainer e não precisam de entradas por locale em strings. Padrão false.
cadenceTargetinteiro (RPM)Alvo opcional de Cadência para o bloco (ex.: 60 para subidas em baixa Cadência, 100 para spin-ups).
cuesarray de CoachingCueAvisos de coaching que disparam durante o bloco.

Avisos de coaching

Um aviso de coaching é uma sobreposição curta de texto que aparece no cockpit durante o pedal. Cada aviso tem um deslocamento dentro do Intervalo pai, o texto a exibir e por quanto tempo deixá-lo na tela.

CampoTipoDescrição
offsetSec obrigatóriointeiro (segundos)Segundos a partir do início do Intervalo pai em que o aviso dispara.
text obrigatóriostringTexto do aviso no locale primário do treino. Variantes entre locales ficam em strings.<locale>.cues, com chave <intervalId>:<cueIndex>.
durationSecinteiro (segundos)Por quanto tempo o aviso permanece na tela. Padrão 5.

Exemplo de Intervalo com três avisos (a composição da chave usa o id do Intervalo pai + o índice do aviso no array):

{
  "id": "work",
  "duration": 600,
  "targetPowerPercent": 95,
  "intensityZone": "Z4",
  "label": "Threshold",
  "intervalType": "INTERVAL",
  "cues": [
    { "offsetSec": 0,   "text": "Settle in — find your rhythm." },
    { "offsetSec": 300, "text": "Halfway. Stay smooth.",  "durationSec": 8 },
    { "offsetSec": 540, "text": "One minute. Hold form." }
  ]
}

Strings localizadas & cadeia de fallback

O bloco strings carrega traduções por locale de cada string visível ao ciclista no treino. Cada entrada de locale tem a mesma forma:

"strings": {
  "en": {
    "name": "Sweet Spot 30",
    "description": "A short sweet-spot workout.",
    "labels": { "warmup": "Warmup", "work": "Sweet Spot", "cooldown": "Cooldown" },
    "cues":   { "work:0": "Settle in", "work:1": "Halfway" }
  },
  "de": {
    "name": "Sweet Spot 30",
    "description": "Ein kurzes Sweet-Spot-Training.",
    "labels": { "warmup": "Aufwärmen", "work": "Sweet Spot", "cooldown": "Ausrollen" },
    "cues":   { "work:0": "Locker einrollen", "work:1": "Halbzeit" }
  }
}

As chaves de avisos seguem o padrão <intervalId>:<cueIndex> — então o primeiro aviso no Intervalo work tem a chave work:0.

Para cada string visível ao ciclista, o app escolhe a melhor correspondência de locale nesta ordem:

  1. strings[<rider-locale>] — o locale do próprio ciclista.
  2. strings[primaryLocale] — o locale do autor.
  3. strings["en"] — fallback universal.
  4. O campo de nível superior (programName, label do Intervalo, text do aviso).

Strings exibidas a partir de qualquer locale que não seja o do próprio ciclista aparecem em itálico nos cards de treino e no cockpit, para que o ciclista saiba quais strings ainda não foram traduzidas.

See also: Habilidades de prompt de IA — the AI Coach can generate strings blocks for additional locales when prompted.

Grupos de repetição

Para estruturas repetitivas, um grupo de repetição escreve a unidade uma única vez e diz ao app quantas vezes reproduzi-la. Os grupos de repetição são expandidos em blocos individuais na importação, para que o ciclista veja cada bloco na faixa de Intervalos seguintes durante o pedal.

{
  "intervals": [
    { "id": "warmup", "duration": 600, "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Warmup", "intervalType": "WARMUP" },
    {
      "repeat": 4,
      "intervals": [
        { "id": "on",  "duration": 480, "targetPowerPercent": 95, "intensityZone": "Z4", "label": "Threshold" },
        { "id": "off", "duration": 240, "targetPowerPercent": 55, "intensityZone": "Z1", "label": "Recovery" }
      ]
    },
    { "id": "cooldown", "duration": 600, "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Cooldown", "intervalType": "COOLDOWN" }
  ]
}

O exemplo acima expande para 1 Aquecimento + 4×(Limiar + Recuperação) + 1 Desaquecimento = 10 blocos. Os grupos de repetição podem ser aninhados, mas o formato plano é preferível para a legibilidade.

Tipos de treino & variantes

O campo workoutType seleciona o paradigma; variant seleciona um subformato dentro dele.

workoutTypeO que éForma de Intervalo exigida
POWER (padrão)Intervalos ancorados no FTP. O trainer mantém a wattagem-alvo em ERG, ou segue curvas de resistência em SIM.Cada Intervalo tem targetPowerPercent (e, opcionalmente, targetPowerEndPercent para rampas).
HR_ZONEIntervalos guiados pela Frequência cardíaca. O trainer ajusta a wattagem em tempo real para manter a FC do ciclista na Zona-alvo — útil quando a carga cardiovascular é a métrica de treino (Recuperação, base, trabalho polarizado).Cada Intervalo tem targetHrZone (1–5). O botão START exibe VINCULAR HRM até que o HRM esteja conectado.
ROUTEPedais de simulação guiados por inclinação. O trainer segue o perfil de elevação a partir de routeProfile; o ciclista escolhe a Cadência e a relação de marchas.Os Intervalos normalmente ficam vazios ou contêm um único placeholder com a duração total. O conteúdo real do pedal fica em routeProfile.

O campo variant seleciona um subformato:

Pacotes (.ytwpack)

Quando você quer um lote curado de treinos de uma só vez, o formato .ytwpack agrupa muitos arquivos .ytw junto com um manifesto por pacote. Um .ytwpack é, no fundo, um arquivo ZIP — renomeie para .zip e descompacte para ver o conteúdo, ou importe-o pelo instalador de pacotes do Your Trainer para instalar todos os treinos com um único toque.

Um arquivo .ytwpack contém:

O manifesto do pacote carrega informação suficiente para uma tela de decisão de instalação sem precisar abrir cada treino. Campos de nível superior:

CampoTipoDescrição
schema_version obrigatóriointeiroAtualmente sempre 1.
pack_id obrigatóriostringIdentificador estável em kebab-case (ex.: sweet-spot).
name obrigatóriostringNome de exibição mostrado no catálogo de pacotes.
description obrigatóriostringResumo de uma ou duas frases visível antes de o ciclista tocar para instalar.
version obrigatóriostring (SemVer)MAJOR.MINOR.PATCH, com -prerelease opcional. Patch para correções de conteúdo; minor para treinos adicionados; major para mudanças incompatíveis no esquema. Incorporado no nome de arquivo publicado (v1.0.2.ytwpack).
content_hash obrigatóriostringsha256: sobre a concatenação ordenada por slug dos bytes de cada arquivo .ytw. Estável entre regenerações de conteúdo inalterado; muda toda vez que os treinos dentro mudam.
generated_at obrigatóriostring (ISO 8601)Timestamp em UTC.
set obrigatóriostringpower ou hr-zone — a família de treino à qual este pacote pertence.
category obrigatóriostringSub-taxonomia dentro do set (ex.: sweet-spot).
workout_count obrigatóriointeiroNúmero de entradas .ytw no pacote.
total_ride_time_seconds obrigatóriointeiroSoma das durações de cada treino no pacote.
experience_level obrigatóriostringCalculado a partir da faixa de dificuldade do conteúdo — um de beginner / intermediate / advanced / mixed. Formato de transmissão em minúsculas; o app capitaliza para exibição.
hrm_required obrigatóriobooleanTrue se algum treino no pacote usar HR_ZONE.
type_mix obrigatórioobjectPercentual por categoria do tempo total de pedal (soma 100). Alimenta o gráfico de rosca de mistura de tipos na tela de instalação no app.
duration_histogram obrigatórioobjectContagem de treinos por faixa de duração: 0-30, 30-60, 60-90, 90+ (minutos). Alimenta o gráfico de duração da tela de instalação.
contents obrigatórioarrayEntradas completas por treino — superconjunto do formato de entrada do manifesto da biblioteca; cada uma traz slug, name, duration_seconds, métricas de resumo, além de um array sparkline para a renderização da miniatura.

Dois caminhos de instalação para um .ytwpack baixado:

Exemplo de manifesto de pacote (com contents truncado para a legibilidade):

{
  "schema_version": 1,
  "pack_id": "sweet-spot",
  "name": "Sweet Spot",
  "description": "26 sweet-spot sessions across classic intervals, sustained stacks, and over-unders.",
  "version": "1.0.2",
  "content_hash": "sha256:9432a3a76015158dc71ec63…",
  "generated_at": "2025-05-28T00:00:00Z",
  "set": "power",
  "category": "sweet-spot",
  "workout_count": 26,
  "total_ride_time_seconds": 119340,
  "experience_level": "intermediate",
  "hrm_required": false,
  "type_mix":   { "sweet-spot": 100 },
  "duration_histogram": { "0-30": 0, "30-60": 5, "60-90": 12, "90+": 9 },
  "contents": [
    { "slug": "sweet-spot-3x10min-at-88pct-ftp",  "name": "Sweet Spot 3×10min @ 88% FTP",  "duration_seconds": 3300, "tss": 55.8,  "intensity_factor": 0.764, "sparkline": […] },
    { "slug": "sweet-spot-3x15min-at-90pct-ftp",  "name": "Sweet Spot 3×15min @ 90% FTP",  "duration_seconds": 4500, "tss": 81.6,  "intensity_factor": 0.808, "sparkline": […] }
    /* … 24 more workouts … */
  ]
}

Manifestos de biblioteca & de pacote

Dois manifestos são publicados ao lado dos artefatos para download. Ambos são JSON puro; ambos são descritos por documentos JSON Schema que você pode obter diretamente.

URLO que ele listaJSON Schema
library/manifest.json Cada .ytw curado na biblioteca — metadados por treino para clientes de navegação / busca / filtro. Também lista os downloads de .ytwpack disponíveis (caminho do arquivo, versão, hash de conteúdo, resumo de mistura de tipos, URL do ícone). /schemas/workout-manifest.json
packs/manifest.json Endpoint do catálogo de pacotes: cada .ytwpack publicado com metadados de resumo. Mesmo formato de entrada por pacote do array packs do manifesto da biblioteca; a Pack Library no app busca isso quando o ciclista solicita uma atualização. /schemas/workout-manifest.json
(dentro de cada .ytwpack) Manifesto por pacote carregado como manifest.json na raiz do arquivo — a tabela acima documenta seu formato. /schemas/workout-pack-manifest.json

Se você está construindo ferramentas que consomem a biblioteca — um navegador de treinos personalizado, um conversor de treinos que tem como alvo .zwo, um painel de coach que exibe pacotes — estes são os contratos contra os quais validar. O mesmo formato de entrada por treino aparece nos arrays contents / workouts de ambos os manifestos, então um cliente que lida com um lida com o outro.

Exemplos resolvidos

Intervalo em rampa

Um Aquecimento de 5 minutos que sobe em rampa de 40 % do FTP a 75 % do FTP via interpolação linear:

{
  "id": "rampup",
  "duration": 300,
  "targetPowerPercent": 40,
  "targetPowerEndPercent": 75,
  "intensityZone": "Z1",
  "label": "Ramp up",
  "intervalType": "WARMUP"
}

Over-under

Três séries de 2 minutos a 95 % do FTP / 1 minuto a 105 % do FTP, expressas como um grupo de repetição:

{
  "repeat": 3,
  "intervals": [
    { "id": "under", "duration": 120, "targetPowerPercent": 95,  "intensityZone": "Z4", "label": "Under" },
    { "id": "over",  "duration": 60,  "targetPowerPercent": 105, "intensityZone": "Z5", "label": "Over"  }
  ]
}

Treino por Zona de FC

Pedal de Resistência de 30 minutos em Z2 com uma arrancada de 3 minutos em Z4 no meio:

{
  "programId": "hr-z2-with-surge",
  "programName": "Z2 with a Z4 surge",
  "description": "Steady Zone 2 with a single 3-minute Zone 4 surge.",
  "totalDuration": 1800,
  "workoutType": "HR_ZONE",
  "primaryLocale": "en",
  "intervals": [
    { "id": "warmup",  "duration": 300,  "targetHrZone": 1, "intensityZone": "Z1", "label": "Warmup", "intervalType": "WARMUP" },
    { "id": "endure1", "duration": 600,  "targetHrZone": 2, "intensityZone": "Z2", "label": "Endurance" },
    { "id": "surge",   "duration": 180,  "targetHrZone": 4, "intensityZone": "Z4", "label": "Surge" },
    { "id": "endure2", "duration": 420,  "targetHrZone": 2, "intensityZone": "Z2", "label": "Endurance" },
    { "id": "cooldown","duration": 300,  "targetHrZone": 1, "intensityZone": "Z1", "label": "Cooldown", "intervalType": "COOLDOWN" }
  ]
}

Multilíngue

O exemplo mínimo de Sweet Spot com blocos strings em EN + DE + NL. Mesmo treino, três experiências nativas:

{
  "programId": "my-sweet-spot",
  "programName": "Sweet Spot 30",
  "description": "A short sweet-spot workout.",
  "totalDuration": 1800,
  "workoutType": "POWER",
  "primaryLocale": "en",
  "intervals": [
    { "id": "warmup",   "duration": 300,  "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Warmup",     "intervalType": "WARMUP"   },
    { "id": "work",     "duration": 1200, "targetPowerPercent": 88, "intensityZone": "Z3", "label": "Sweet Spot", "intervalType": "INTERVAL",
      "cues": [
        { "offsetSec": 0,   "text": "Settle in" },
        { "offsetSec": 600, "text": "Halfway" }
      ]
    },
    { "id": "cooldown", "duration": 300,  "targetPowerPercent": 50, "intensityZone": "Z1", "label": "Cooldown",   "intervalType": "COOLDOWN" }
  ],
  "strings": {
    "en": {
      "name": "Sweet Spot 30",
      "description": "A short sweet-spot workout.",
      "labels": { "warmup": "Warmup", "work": "Sweet Spot", "cooldown": "Cooldown" },
      "cues":   { "work:0": "Settle in", "work:1": "Halfway" }
    },
    "de": {
      "name": "Sweet Spot 30",
      "description": "Ein kurzes Sweet-Spot-Training.",
      "labels": { "warmup": "Aufwärmen", "work": "Sweet Spot", "cooldown": "Ausrollen" },
      "cues":   { "work:0": "Locker einrollen", "work:1": "Halbzeit" }
    },
    "nl": {
      "name": "Sweet Spot 30",
      "description": "Een korte sweet-spot-training.",
      "labels": { "warmup": "Inrijden", "work": "Sweet Spot", "cooldown": "Uitrijden" },
      "cues":   { "work:0": "Rustig inrijden", "work:1": "Halverwege" }
    }
  }
}

Armadilhas comuns

Referência

Para buscas programáticas de spec de formato (tabelas de campos, exemplos, constraints, glossário), a fonte canônica legível por máquina é o Your Trainer MCP — chame get_format_spec, get_canonical_examples, get_format_constraints ou get_format_glossary de qualquer cliente MCP. Essas tools servem do mesmo registro de conhecimento que alimenta esta página; se a resposta de uma tool alguma vez divergir desta página, o MCP é canônico e esta página está obsoleta.

JSON Schemas (contratos legíveis por máquina para clientes que constroem sobre estes formatos):

← Voltar ao Manual & Guias