Schéma de séance
Dernière mise à jour : 2026-05-29
Your Trainer est une application de cyclisme en intérieur multi-cyclistes pour tablettes Android. Contrôle du home-trainer avec données locales + contrôle local. Achat unique.
Le fichier de séance .ytw est du JSON brut — rédige-le dans n'importe quel éditeur de texte, importe-le via la feuille de partage, partage-le avec tes amis. L'éditeur visuel gère les cas courants ; le schéma est l'échappatoire quand tu as besoin d'un contrôle total.
Quand rédiger à la main
La plupart des cyclistes n'ont jamais besoin de cette page — l'éditeur visuel de séances et l'AI Workout Coach couvrent tout, d'une séance de 4×8 au Seuil à un empilement de microbursts. Tourne-toi vers le schéma quand :
- Tu veux une structure que l'éditeur n'expose pas (échauffements très longs, script d'indications élaboré, cibles de cadence mixtes par intervalle).
- Tu traduis une séance que tu possèdes déjà dans le format d'un autre outil.
- Tu veux envoyer une séance à quelqu'un d'autre sous forme de fichier unique.
- Tu veux générer des séances en masse de manière programmatique.
Exemple minimal
Le plus court fichier .ytw valide est un programme avec un seul intervalle. Enregistre-le avec l'extension .ytw et partage-le vers 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" }
]
}
Champs de premier niveau
L'objet de premier niveau décrit un programme de séance. Les champs requis sont signalés.
| Champ | Type | Description |
|---|---|---|
programId requis | chaîne | Identifiant stable. Utilise le kebab-case (my-sweet-spot). La clé unique de la séance dans ta bibliothèque — réimporter un fichier avec le même programId met à jour l'entrée existante au lieu d'en créer un doublon. |
programName requis | chaîne | Nom affiché dans la langue principale du cycliste. |
description requis | chaîne | Description d'une ou deux phrases affichée sur la carte de la séance. |
totalDuration requis | entier (secondes) | Durée totale de la séance. L'app la recalcule à partir des intervalles à l'enregistrement, donc tu peux la laisser incohérente pendant la rédaction. |
intervals requis | tableau | Liste ordonnée d'objets intervalle ou de groupes de répétition. |
workoutType | chaîne | Famille de séance : POWER (par défaut), HR_ZONE ou ROUTE. Voir Types de séance. |
variant | chaîne | Sous-forme à l'intérieur de la famille : STANDARD (par défaut) ou RAMP_TEST. |
primaryLocale | chaîne (BCP-47) | Langue dans laquelle les chaînes ont été rédigées. Par défaut "en". Pilote la chaîne de repli inter-langues. |
category | chaîne | Catégorisation en texte libre (par exemple "threshold", "endurance"). Optionnel. |
difficulty | entier (1–5) | Difficulté subjective. Apparaît sur la carte de la séance. |
isUserCreated | booléen | Vrai pour les séances créées dans l'app par le cycliste ; faux pour les séances importées ou fournies. Par défaut false. |
isFavorite | booléen | Indicateur d'épinglage en haut. Les cyclistes le basculent dans l'app ; généralement omis dans les fichiers partagés. |
routeProfile | tableau de { distanceMeters, elevationMeters } | Profil d'élévation complet pour les séances ROUTE. Null pour POWER et HR_ZONE. |
strings | objet (langue → LocaleStrings) | Traductions par langue du nom, de la description, des étiquettes d'intervalles et des indications. |
Champs d'intervalle
Chaque objet intervalle décrit un bloc de la séance. La forme du bloc dépend du workoutType parent — les blocs Power utilisent des pourcentages de puissance, les blocs HR-Zone utilisent une cible de zone.
| Champ | Type | Description |
|---|---|---|
duration requis | entier (secondes) | Durée du bloc en secondes. |
targetPowerPercent requis pour power | entier (% de la FTP) | Cible de puissance pour les séances POWER. Mutuellement exclusif avec targetHrZone. |
targetPowerEndPercent | entier (% de la FTP) | Puissance de fin de rampe optionnelle. Lorsqu'elle est présente, le wattage cible s'interpole linéairement de targetPowerPercent → targetPowerEndPercent sur la durée du bloc. |
targetHrZone requis pour hr | entier (1–5) | Zone de FC pour les séances HR_ZONE. Mutuellement exclusif avec targetPowerPercent. |
intensityZone requis | chaîne | Jeton visuel de zone : Z1–Z5. Pilote la couleur sur la visualisation du terrain. Voir Zones d'entraînement. |
intervalType | chaîne | WARMUP, COOLDOWN ou INTERVAL (par défaut). Les blocs d'Échauffement et de Retour au calme sont exclus des résumés portant sur le seul travail (puissance moyenne des blocs de travail, temps en zone pour la portion de travail, etc.). |
label requis | chaîne | Texte affiché sur le bloc dans la langue principale du cycliste. Les variantes inter-langues se trouvent dans strings.<locale>.labels. |
id | chaîne | Slug stable — la clé utilisée dans strings.<locale>.labels et dans la composition des clés d'indication. Recommandé pour toute séance livrée avec des traductions. |
autoLabel | booléen | Vrai lorsque l'étiquette a été générée par un préréglage de l'éditeur plutôt que saisie par le cycliste. Les étiquettes automatiques sont localisées par Your Trainer lui-même et n'ont pas besoin d'entrées par langue dans strings. Par défaut false. |
cadenceTarget | entier (RPM) | Cible de Cadence optionnelle pour le bloc (par exemple 60 pour de la grimpée à basse Cadence, 100 pour des exercices d'accélération de pédalage). |
cues | tableau de CoachingCue | Indications de coaching qui se déclenchent pendant le bloc. |
Indications de coaching
Une indication de coaching est un court texte qui apparaît en surimpression sur le cockpit pendant une sortie. Chaque indication a un décalage à l'intérieur de son intervalle parent, le texte à afficher et la durée pendant laquelle elle reste à l'écran.
| Champ | Type | Description |
|---|---|---|
offsetSec requis | entier (secondes) | Secondes depuis le début de l'intervalle parent auxquelles l'indication se déclenche. |
text requis | chaîne | Texte de l'indication dans la langue principale de la séance. Les variantes inter-langues se trouvent dans strings.<locale>.cues, indexées par <intervalId>:<cueIndex>. |
durationSec | entier (secondes) | Durée pendant laquelle l'indication reste à l'écran. Par défaut 5. |
Exemple d'intervalle avec trois indications (la composition de clé utilise l'id de l'intervalle parent + l'index de l'indication dans le tableau) :
{
"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." }
]
}
Chaînes localisées et chaîne de repli
Le bloc strings porte les traductions par langue de chaque chaîne visible par le cycliste dans la séance. Chaque entrée de langue a la même forme :
"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" }
}
}
Les clés d'indication suivent le motif <intervalId>:<cueIndex> — donc la première indication sur l'intervalle work a la clé work:0.
Pour chaque chaîne visible par le cycliste, l'app choisit la meilleure correspondance de langue dans cet ordre :
strings[<rider-locale>]— la propre langue du cycliste.strings[primaryLocale]— la langue de l'auteur.strings["en"]— repli universel.- Le champ de premier niveau (
programName,labeld'intervalle,textd'indication).
Les chaînes affichées depuis toute langue autre que celle du cycliste apparaissent en italique sur les cartes de séance et le cockpit, afin que le cycliste sache quelles chaînes n'ont pas encore été traduites.
strings blocks for additional locales when prompted.Groupes de répétition
Pour les structures répétitives, un groupe de répétition rédige l'unité une seule fois et indique à l'app combien de fois la jouer. Les groupes de répétition sont déployés en blocs individuels à l'import, afin que le cycliste voie chaque bloc dans la bande des intervalles à venir pendant la sortie.
{
"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" }
]
}
L'exemple ci-dessus se déploie en 1 Échauffement + 4×(Seuil + Récupération) + 1 Retour au calme = 10 blocs. Les groupes de répétition peuvent être imbriqués, mais le plat est préférable pour la lisibilité.
Types de séance et variantes
Le champ workoutType sélectionne le paradigme ; variant sélectionne une sous-forme à l'intérieur.
workoutType | De quoi il s'agit | Forme d'intervalle requise |
|---|---|---|
POWER (par défaut) | Intervalles ancrés sur la FTP. Le home-trainer roule au wattage cible en ERG, ou suit des courbes de résistance en SIM. | Chaque intervalle a targetPowerPercent (et optionnellement targetPowerEndPercent pour les rampes). |
HR_ZONE | Intervalles pilotés par la Fréquence cardiaque. Le home-trainer ajuste le wattage en direct pour maintenir la FC du cycliste dans la zone cible — utile lorsque la charge cardiovasculaire est la métrique d'entraînement (Récupération, base, travail polarisé). | Chaque intervalle a targetHrZone (1–5). Le bouton START affiche LIER HRM jusqu'à ce que le HRM soit connecté. |
ROUTE | Sorties de simulation pilotées par la pente. Le home-trainer suit le profil d'élévation depuis routeProfile ; le cycliste choisit la Cadence et le braquet. | Les intervalles sont généralement vides ou contiennent un seul espace réservé pleine longueur. Le vrai contenu de la sortie se trouve dans routeProfile. |
Le champ variant sélectionne une sous-forme :
STANDARD(par défaut) — séance structurée ordinaire.RAMP_TEST— signalé comme un test de FTP. Invite le cycliste à mettre à jour sa FTP à la fin de la sortie et est exclu des résumés de charge d'entraînement (afin qu'un effort maximal ne fausse pas le graphique de charge hebdomadaire).
Packs (.ytwpack)
Quand tu veux un lot organisé de séances en une seule fois, le format .ytwpack regroupe plusieurs fichiers .ytw avec un manifeste par pack. Un .ytwpack est une archive ZIP sous le capot — renomme-le en .zip et décompresse-le pour voir le contenu, ou importe-le via l'installateur de packs de Your Trainer pour installer toutes les séances en un seul tap.
Une archive .ytwpack contient :
manifest.jsonà la racine de l'archive — les métadonnées au niveau du pack décrites ci-dessous.- Un
<slug>.ytwpar séance dans le pack, où chaque fichier suit le schéma documenté ci-dessus.
Le manifeste du pack contient assez d'informations pour une fiche de décision d'installation sans avoir besoin d'ouvrir chaque séance. Champs de premier niveau :
| Champ | Type | Description |
|---|---|---|
schema_version requis | entier | Actuellement toujours 1. |
pack_id requis | chaîne | Identifiant stable en kebab-case (par exemple sweet-spot). |
name requis | chaîne | Nom affiché dans le catalogue de packs. |
description requis | chaîne | Résumé d'une ou deux phrases visible avant que le cycliste ne tape pour installer. |
version requis | chaîne (SemVer) | MAJOR.MINOR.PATCH, -prerelease optionnel. Patch pour les correctifs de contenu ; mineure pour des séances additives ; majeure pour des changements de schéma cassants. Intégré dans le nom de fichier publié (v1.0.2.ytwpack). |
content_hash requis | chaîne | sha256: sur la concaténation triée par slug des octets de chaque fichier .ytw. Stable d'une régénération à l'autre pour un contenu inchangé ; augmente chaque fois que les séances à l'intérieur changent. |
generated_at requis | chaîne (ISO 8601) | Horodatage UTC. |
set requis | chaîne | power ou hr-zone — la famille de séances à laquelle ce pack appartient. |
category requis | chaîne | Sous-taxonomie à l'intérieur du set (par exemple sweet-spot). |
workout_count requis | entier | Nombre d'entrées .ytw dans le pack. |
total_ride_time_seconds requis | entier | Somme des durées de chaque séance dans le pack. |
experience_level requis | chaîne | Calculé à partir de la plage de difficulté des contenus — l'un de beginner / intermediate / advanced / mixed. Format de fil en minuscules ; l'app met une majuscule pour l'affichage. |
hrm_required requis | booléen | Vrai si une séance du pack utilise HR_ZONE. |
type_mix requis | objet | Pourcentage par catégorie du temps total de sortie (somme à 100). Pilote le donut de répartition par type sur la fiche d'installation dans l'app. |
duration_histogram requis | objet | Nombre de séances par tranche de durée : 0-30, 30-60, 60-90, 90+ (minutes). Pilote le graphique de durée de la fiche d'installation. |
contents requis | tableau | Entrées complètes par séance — sur-ensemble de la forme d'entrée du manifeste de bibliothèque ; chacune porte slug, name, duration_seconds, des métriques de résumé, plus un tableau sparkline pour le rendu de la vignette. |
Deux chemins d'installation pour un .ytwpack téléchargé :
- Installation en un tap dans Your Trainer — ouvre le
.ytwpackdans la feuille de partage, Your Trainer lit le manifeste du pack, te montre ce qu'il contient (répartition par type, histogramme de durée, temps total de sortie) et installe toutes les séances d'un coup. Disponible une fois que l'installateur de packs intégré à l'app sera livré. - Décompression manuelle — renomme en
.zip(ou décompresse directement avec n'importe quel outil d'archive), puis partage chaque.ytwvers Your Trainer un par un via la feuille de partage.
Exemple de manifeste de pack (avec contents tronqué pour la lisibilité) :
{
"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 … */
]
}
Manifestes de bibliothèque et de pack
Deux manifestes sont publiés aux côtés des artefacts téléchargeables. Les deux sont en JSON brut ; les deux sont décrits par des documents JSON Schema que tu peux récupérer directement.
| URL | Ce qu'il liste | JSON Schema |
|---|---|---|
library/manifest.json |
Chaque .ytw organisé dans la bibliothèque — métadonnées par séance pour les clients de navigation / recherche / filtre. Liste également les téléchargements .ytwpack disponibles (chemin de fichier, version, hash de contenu, résumé de répartition par type, URL d'icône). |
/schemas/workout-manifest.json |
packs/manifest.json |
Point d'accès du catalogue de packs : chaque .ytwpack publié avec ses métadonnées de résumé. Même forme d'entrée par pack que le tableau packs du manifeste de bibliothèque ; la Pack Library intégrée à l'app récupère cela sur rafraîchissement initié par le cycliste. |
/schemas/workout-manifest.json |
(à l'intérieur de chaque .ytwpack) |
Manifeste par pack transporté en tant que manifest.json à la racine de l'archive — le tableau ci-dessus en documente la forme. |
/schemas/workout-pack-manifest.json |
Si tu construis un outil qui consomme la bibliothèque — un navigateur de séances sur mesure, un convertisseur de séances qui cible .zwo, un tableau de bord d'entraîneur qui fait apparaître des packs — ce sont les contrats à valider. La même forme d'entrée par séance apparaît dans les tableaux contents / workouts des deux manifestes, donc un client qui gère l'un gère l'autre.
Exemples détaillés
Intervalle en rampe
Un Échauffement de 5 minutes qui monte de 40 % de FTP à 75 % de FTP par interpolation linéaire :
{
"id": "rampup",
"duration": 300,
"targetPowerPercent": 40,
"targetPowerEndPercent": 75,
"intensityZone": "Z1",
"label": "Ramp up",
"intervalType": "WARMUP"
}
Over-under
Trois séries de 2 minutes à 95 % de FTP / 1 minute à 105 % de FTP, exprimées sous forme de groupe de répétition :
{
"repeat": 3,
"intervals": [
{ "id": "under", "duration": 120, "targetPowerPercent": 95, "intensityZone": "Z4", "label": "Under" },
{ "id": "over", "duration": 60, "targetPowerPercent": 105, "intensityZone": "Z5", "label": "Over" }
]
}
Séance par zones de FC
Sortie d'Endurance Z2 de 30 minutes avec une accélération Z4 de 3 minutes au milieu :
{
"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" }
]
}
Multilingue
L'exemple minimal Sweet Spot avec des blocs strings EN + DE + NL. Même séance, trois expériences natives :
{
"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" }
}
}
}
Pièges courants
idmanquant sur les intervalles. Le runtime accepte les intervalles sansid, mais tu perdras tes points d'entrée de traduction —strings.<locale>.labelset la table des clés d'indication en dépendent tous les deux. Si tu comptes livrer une séance avecstrings, donne unidà chaque intervalle.- Clés d'indication mal alignées. Le motif de clé d'indication est
<intervalId>:<cueIndex>— indexé à partir de zéro. La troisième indication sur l'intervalleworkestwork:2, paswork:3. targetPowerPercentettargetHrZonetous les deux sur le même intervalle. Ils sont mutuellement exclusifs — garde l'un ou l'autre selon leworkoutTypeparent.- Oubli d'
intervalTypesur les échauffements et retours au calme. La valeur par défaut estINTERVAL— règle explicitementWARMUP/COOLDOWNpour que la couche d'analyse n'agrège pas ces blocs dans le total de travail. totalDurationgonflé. Sans gravité pendant la rédaction — Your Trainer le recalcule à partir d'intervalsà l'enregistrement. Mais ça vaut la peine de le corriger avant de partager, parce que certains outils externes affichent ce champ tel quel.- Mauvais jeton
intensityZone. Doit être l'un deZ1–Z5sous forme de chaîne."Z6"ou"3"n'affichera pas la bonne couleur sur la visualisation du terrain.
Référence
- L'AI Workout Coach génère du JSON
.ytwvalide à partir d'une description en texte brut — utile comme point de départ que tu retouches ensuite à la main. - Pour la création programmatique déterministe (sans LLM) : Your Trainer MCP — Documentation pour intégrateurs couvre
build_workout_from_intentetdecompose_workout, qui se composent vers / depuis ce schéma. - Pour les séances qui ne s'importent pas : Dépannage → Imports de séances et de parcours.
- Pour les définitions de zones : Zones d'entraînement.
- Pour les termes peu familiers : Glossaire.
- Les séances livrées avec Your Trainer exercent chaque forme prise en charge par le schéma — en examiner une dans un éditeur de texte (exportée depuis l'éditeur visuel) est un moyen rapide de voir un vrai exemple de n'importe quel champ.
Pour des recherches programmatiques de spec de format (tables de champs, exemples, contraintes, glossaire), la source canonique lisible par machine est le Your Trainer MCP — appelez get_format_spec, get_canonical_examples, get_format_constraints ou get_format_glossary depuis n'importe quel client MCP. Ces outils servent depuis le même registre de connaissances qui alimente cette page ; si la réponse d'un outil diverge un jour de cette page, le MCP est canonique et cette page est obsolète.
JSON Schemas (contrats lisibles par machine pour les clients qui construisent sur ces formats) :
/schemas/workout-manifest.json— manifeste de bibliothèque + forme d'entrée par pack (couvre à la foislibrary/manifest.jsonetpacks/manifest.json)./schemas/workout-pack-manifest.json— lemanifest.jsontransporté à l'intérieur de chaque.ytwpack./schemas/workout-intent.json— forme d'intention structurée utilisée par les outils de rédaction de séances qui composent vers.ytw.