[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XCXT4GZHCNGJ9HHHV5B1AT":3,"skill-same:01M6XCXT4GZHCNGJ9HHHV5B1AT":106},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":43,"commitSha":44,"skillDirectory":45,"forksCount":14,"repositoryHtmlUrl":46,"repositoryHomepageUrl":6,"ownerHtmlUrl":47,"ownerBlogUrl":48,"ownerDescription":6,"updatedAt":49,"install":50,"resources":63},"01M6XCXT4GZHCNGJ9HHHV5B1AT","bitmovin-encoding-vod",null,"Guide a user through creating and starting a Bitmovin VOD encoding (H.264 per-title, H.264 fixed ladder, AV1 per-title for UGC, H.264 hardware-accelerated sports clips, or a custom-built template assembled from the user's free-text use case using the Encoding Template schema and a cross-field rulebook) end-to-end via the Bitmovin CLI's Encoding Templates commands.","bitmovin\u002Fskills","bitmovin","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F3273006?v=4","01M6XCX24ZDCBTPHWAAM18VJQY","Bitmovin","01M6XCX29H5E446MM0E5XAVQTC",1,"MIT","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002FSKILL.md",[],[19,20,9,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"encoding","bitmovin encoding vod","via","cli","templates","title","custom","sports","for","ladder","case","template","free","end","commands","schema","use","guide","text","2026-11-10 10:12:30",false,"---\nname: bitmovin-encoding-vod\ndescription: Guide a user through creating and starting a Bitmovin VOD encoding (H.264 per-title, H.264 fixed ladder, AV1 per-title for UGC, H.264 hardware-accelerated sports clips, or a custom-built template assembled from the user's free-text use case using the Encoding Template schema and a cross-field rulebook) end-to-end via the Bitmovin CLI's Encoding Templates commands.\n---\n\n# Bitmovin VOD Encoding Skill\n\nWalks the user through configuring and starting a Bitmovin VOD encoding.\nThe heavy lifting is done by the Bitmovin **Encoding Templates API**: a\nsingle `POST \u002Fencoding\u002Ftemplates\u002Fstart` creates inputs, codec configs,\nencoding, streams, muxings, manifests **and** starts the encoding from\none YAML document.\n\nThis skill renders that YAML from a small parameter file, validates and\nsubmits it via the **Bitmovin CLI** (`bitmovin encoding ...`), polls\nuntil the encoder reaches `FINISHED`, and points the user at the\ndashboard to grab manifest URLs.\n\n## Prerequisites\n\n- **Bitmovin CLI** (`@bitmovin\u002Fcli`, ≥ 0.2.0) — drives `inputs list\u002Fcreate`,\n  `outputs list\u002Fcreate`, `templates validate`, `templates start`,\n  `jobs get`, `jobs status`. Install with `npm install -g @bitmovin\u002Fcli`.\n- **Python ≥ 3.10** — Step 1's `scripts\u002Fensure_venv.sh` auto-creates a\n  dedicated venv and installs `pyyaml` and `jinja2` into it if they\n  aren't already importable from the user's `python3`. Used only by the\n  inline Jinja render block in Step 6 and by `validate_rules.py` in\n  Step 7; every other workflow step is the CLI.\n- `BITMOVIN_API_KEY` environment variable set.\n- For creating a new output (optional): `BITMOVIN_OUTPUT_ACCESS_KEY` \u002F\n  `BITMOVIN_OUTPUT_SECRET_KEY` env vars (see Step 4). Credentials are\n  read from the environment and passed to the CLI via shell expansion at\n  invocation time — never hardcoded into scripts, the params file, or\n  the rendered template.\n\nThe skill never embeds secrets in the rendered template or log output.\nInputs that need credentials (S3, GCS, Azure, …) must be **reused** via\nan existing input id — they are never created from this skill, since\nthat would require pasting credentials into a parameter file.\n\n## Path Conventions\n\n- `SKILL_DIR`: install location of this skill (e.g.\n  `~\u002F.claude\u002Fskills\u002Fbitmovin-encoding-vod` or\n  `~\u002F.codex\u002Fskills\u002Fbitmovin-encoding-vod`). Used to locate `scripts\u002F` and\n  `templates\u002F`.\n- `RUN_DIR`: per-run cache directory at\n  `~\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F\u003Crun-id>\u002F`, where `\u003Crun-id>` is\n  `YYYYMMDD-HHMMSS-\u003Cshort-hash>`. Holds the rendered template and a copy\n  of the params file. RUN_DIR MUST stay outside the skill directory so\n  its contents are never published or installed.\n\n## Scripts\n\n| Script | Purpose |\n|---|---|\n| `scripts\u002Fensure_venv.sh` | Prints the path to a Python interpreter that has `pyyaml` and `jinja2` available. Uses the user's `python3` if it already has them; otherwise creates \u002F reuses a venv at `~\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F.venv\u002F` and installs the deps there. |\n| `scripts\u002Fvalidate_rules.py \u003Ctemplate.yaml>` | Runs cross-field rule checks (see `references\u002Frulebook.yaml`) against a rendered Encoding Template. Catches semantic errors the JSON schema can't express — fMP4-stream-count, AV1 min bitrate (with per-title carve-out), per-title bitrate algebra, hardware-encoding limits, sprite\u002Fthumbnail rules, Dolby Vision constraints. Exits non-zero on violations. Always run between `bitmovin encoding templates validate` and `bitmovin encoding templates start`. |\n\nAll other workflow steps — input listing \u002F creation, output listing \u002F\ncreation, template validation \u002F submission, status polling — are driven\ndirectly by the Bitmovin CLI from the inline shell snippets in this\ndocument. SKILL.md is responsible for prompting the user.\n\n## References\n\n| File | Purpose |\n|---|---|\n| `references\u002Frulebook.yaml` | Cross-field semantic rules for VOD encodings, derived from Bitmovin's server-side validators. Each rule has an `id`, a `rule` description, and an `applies_when` predicate. Consulted during the custom-build flow (Step 2b) to prune options the API would reject; enforced post-render by `validate_rules.py`. |\n\n## Templates\n\nJinja2 templates in `\u003CSKILL_DIR>\u002Ftemplates\u002F`:\n\n| Template | Use case |\n|---|---|\n| `per-title-h264.yaml.j2` | H.264 Per-Title encoding — Bitmovin's algorithm picks an optimal bitrate ladder per input. Includes a 1080p fixed-resolution anchor so the ladder always reaches HD when the source supports it. THREE_PASS encoding. Default DASH + HLS manifests. |\n| `fixed-ladder-h264.yaml.j2` | H.264 fixed bitrate ladder — encode the renditions you specify in `videoLadder`. Predictable output sizes, fast encode (single-pass by default). Default DASH + HLS manifests. |\n| `av1-per-title-ugc.yaml.j2` | AV1 Per-Title for viral \u002F UGC pipelines — ~50% bitrate savings vs H.264. Emits a progressive MP4 file per rendition (no fmp4 segments, no DASH\u002FHLS manifest), video-only. Includes a 1080p fixed-resolution anchor. THREE_PASS encoding. |\n| `sports-clips-h264.yaml.j2` | H.264 sports-clips workflow optimized for time-to-publish — NVIDIA-GPU-backed `VOD_HARDWARE_SHORTFORM` preset, 9-rendition ladder (360p–1080p with multi-bitrate steps at 540p\u002F720p\u002F1080p), HLS-only with explicit per-rendition manifest config. Pinned to `cloudRegion: AWS_EU_WEST_1` (required for the hardware preset). Video-only, ACL=PRIVATE by default. |\n\nThe H.264 per-title \u002F fixed-ladder templates produce CMAF-style fmp4\nwith default DASH+HLS manifests. The AV1 UGC template produces\nprogressive MP4 files without manifests. The sports-clips template\nproduces fmp4 with HLS-only manifests and uses a hardcoded ladder.\nCustomers can hand-edit the rendered YAML before\n`bitmovin encoding templates start` if they need variants (more\nrenditions, different segment naming, additional muxing types).\n\n`\u003CSKILL_DIR>\u002Fexamples\u002Fparams.example.yaml` documents every parameter.\n\n## Workflow\n\n### Step 1 — Verify prerequisites\n\nConfirm the Bitmovin CLI is installed and resolve the Python interpreter\nthat has the runtime deps (used by Steps 6 and 7):\n\n```bash\ncommand -v bitmovin >\u002Fdev\u002Fnull \\\n  || { echo \"error: bitmovin CLI not found. Install with: npm install -g @bitmovin\u002Fcli\" >&2; exit 1; }\nPYTHON=$(bash \u003CSKILL_DIR>\u002Fscripts\u002Fensure_venv.sh) || exit 1\ntest -n \"$BITMOVIN_API_KEY\" || { echo \"error: BITMOVIN_API_KEY is not set\" >&2; exit 1; }\necho \"OK ($PYTHON)\"\n```\n\n`$PYTHON` is reused in Steps 6 and 7. If `BITMOVIN_API_KEY` is empty,\nask the user to export it before continuing. The CLI reads the key from\nthe same env var, so no extra config is required.\n\nIf `python3` itself is missing, `ensure_venv.sh` prints a clear error\nand exits non-zero — point the user at https:\u002F\u002Fwww.python.org\u002Fdownloads\u002F\n(Python ≥ 3.10).\n\n### Step 2 — Pick scenario\n\nAsk the user which template to use. These are the only valid choices —\ndo **not** offer an `Other (specify)` free-text fallback. The fifth\noption is the explicit escape hatch:\n\n1. `per-title-h264` — H.264 Per-Title (default; let the algorithm pick the ladder)\n2. `fixed-ladder-h264` — H.264 fixed ladder (you specify the renditions)\n3. `av1-per-title-ugc` — AV1 Per-Title for UGC pipelines (progressive MP4, no manifests, ~50% bitrate savings vs H.264)\n4. `sports-clips-h264` — H.264 sports clips with NVIDIA hardware acceleration (VOD_HARDWARE_SHORTFORM preset, HLS-only, hardcoded sports ladder, time-to-publish optimized)\n5. `custom` — none of the above fits; describe the use case in free text and the skill assembles a template from the schema + rulebook (see Step 2b)\n\nFor options 1–4, map to the matching template under\n`\u003CSKILL_DIR>\u002Ftemplates\u002F`. For option 5, jump to **Step 2b** before Step 3.\n\n### Step 2b — Custom Build (only when scenario = `custom`)\n\nThe user has described a use case the four prebaked scenarios don't fit.\nThe skill guides them through assembling a template from primitives,\nfiltering options at each decision using the cross-field rulebook so\nchoices that the API would reject never appear.\n\n**Sources of truth, in order of authority:**\n\n1. `\u003CSKILL_DIR>\u002Freferences\u002Frulebook.yaml` — semantic compatibility rules\n   derived from Bitmovin's server-side validators. Each rule has an\n   `applies_when` predicate; if it matches the user's choices, apply the\n   rule's constraint. Every rule applies to VOD (live-only rules have\n   been removed).\n2. `~\u002F.config\u002Fbitmovin\u002Ftemplate-schema-v1.json` — the published Encoding\n   Template JSON Schema (24h-cached by `bitmovin encoding templates\n   validate`). Use it to discover allowed values for enum fields\n   (codecs, profiles, manifest types, DRM types, ACL permissions, …).\n   If the cache is missing, run `bitmovin encoding templates validate`\n   against any prebaked template once to warm it, or fall back to the\n   four existing templates as worked examples.\n3. `\u003CSKILL_DIR>\u002Ftemplates\u002F*.yaml.j2` — worked examples of valid template\n   shapes. Read at least one matching the user's container choice\n   (fmp4 \u002F progressive mp4 \u002F hls-only) before authoring.\n\n**Workflow:**\n\n1. **Capture the use case.** Take the user's free-text description.\n   Re-state your understanding back in one sentence and confirm before\n   continuing.\n\n2. **Walk a decision tree.** Ask **one question at a time** with a\n   selectable picker. After each answer, consult the rulebook: drop any\n   downstream option whose `applies_when` would conflict with the\n   answers so far. Order:\n\n   a. **Video codec(s)** — h264 (broadest device support), h265\n      (~50% bandwidth savings), av1 (~50% savings, newer; rule\n      `codec.av1.min_bitrate` requires bitrate ≥ 10000 unless\n      per-title). Multi-codec ladders allowed.\n   b. **Encoding strategy** — per-title (algorithm-driven ladder, runs\n      THREE_PASS), fixed ladder (renditions you list), single rendition.\n   c. **Audio** — AAC (default), Dolby Atmos \u002F DD+ (rule\n      `dd.drm_encoder_features` gates with DRM; rule `dd.invalid_filters`\n      blocks AUDIO_VOLUME \u002F WATERMARK \u002F ENHANCED_WATERMARK), pass-through,\n      or none (video-only).\n   d. **Muxing format** — fmp4 (CMAF-style; works with DASH and HLS;\n      rule `muxing.fmp4.exactly_one_stream` means one muxing per\n      stream), progressive MP4 (single file, no manifest), TS, CMAF.\n      For fmp4 + AV1, rule `muxing.mp4_fragmented.av1_manifest_type`\n      restricts manifest type to DASH_ON_DEMAND or NONE.\n   e. **Manifest format** — DASH only, HLS only, both, none. Default-API\n      manifests (`defaultapi.\u003Cid>`) are simpler than custom; prefer them\n      unless the user needs custom adaptation sets.\n   f. **DRM** (optional) — none (default), Widevine, PlayReady, FairPlay,\n      multi-DRM via CencDrm. Rulebook gates: `drm.fmp4.fairplay_codec`\n      requires HEVC for fmp4+FairPlay unless encoder version supports\n      `FIXED_ENCRYPTION_METHOD_SELECTION`.\n   g. **HDR \u002F Dolby Vision** (optional) — none (default), HDR10, Dolby\n      Vision. DV pulls in many rules (`dv.input_codec_allowlist` →\n      H.264\u002FH.265 only, `dv.muxing_audio_codec_allowlist` → AAC\u002FAtmos\n      audio, `dv.pixel_format` → YUV420P10LE, `dv.bufsize_maxrate_required`\n      except per-title which uses `dv.per_title_factors_required`).\n      Walk these explicitly with the user.\n   h. **Hardware acceleration** (optional) — none (default), or NVIDIA\n      preset. Hardware encoding pulls in rules `hw.vod_only`,\n      `hw.aws_only`, `hw.no_per_title`, `hw.no_dolby_vision`,\n      `hw.no_filters`, `hw.no_thumbnails`, `hw.no_psnr`, etc. — if the\n      user already chose per-title or DV, hardware is no longer offered.\n   i. **Out-of-scope features** — sprites, subtitles (CEA \u002F WebVTT \u002F\n      IMSC), filters (watermark \u002F scale \u002F crop), SCTE-35,\n      concatenation, multi-period DASH. If the user needs any of\n      these, point them at https:\u002F\u002Fdeveloper.bitmovin.com\u002Fencoding\u002Fdocs\n      and stop the custom build (the rulebook covers some of these but\n      the skill does not yet author the YAML for them).\n\n3. **Author the YAML.** Once the decision tree is complete, write\n   `$RUN_DIR\u002Ftemplate.yaml` directly. Use the prebaked templates as\n   structural examples. Required top-level keys: `metadata` (with\n   `type: VOD`), `configurations`, `encodings`, optionally `manifests`.\n   Reference inputs\u002Foutputs by id (Steps 3 + 4). Show the assembled\n   YAML to the user and confirm before continuing.\n\n4. **Rejoin Step 7.** Skip Steps 5 (gather params) and 6 (render\n   template) — the YAML is already authored. Step 7 runs\n   `bitmovin encoding templates validate` plus `validate_rules.py`, so\n   if any rulebook constraint was missed during the decision tree, it\n   surfaces as a violation before the submit.\n\nIf, during the decision tree, the user picks a combination that the\nrulebook says is impossible (e.g. hardware + per-title), stop, explain\nwhich rule blocks it (cite `rule.id`), and ask the user to revisit the\nprior decision.\n\n### Step 3 — Input source\n\nAsk whether to **reuse** an existing input or **create** a fresh HTTPS\ninput. The skill never accepts credentials, so for S3\u002FGCS\u002FAzure the\ninput must already exist in the account.\n\n**Reuse**: optionally run `bitmovin encoding inputs list --type s3`\n(filter with `--type https`, `--type gcs`, etc. if the user knows the\ntype) to surface candidates. Capture the `id` from the user. Persist it\nas `inputId` in the working `params.yaml`.\n\n**Create HTTPS**: ask for the host (no scheme, no path — e.g.\n`bitmovin-sample-content.s3.eu-west-1.amazonaws.com`) and a name. Then\nrun:\n\n```bash\nbitmovin encoding inputs create https \\\n  --name \"\u003CNAME>\" --host \"\u003CHOST>\" \\\n  --json --jq .id\n```\n\nIt prints the new `input_id`. Persist it as `inputId` in `params.yaml`.\n\nIn **both** cases, also ask for `inputPath` — the path to the input file\n*inside* the input source (e.g. `\u002Fsintel\u002Fsintel.mp4` or\n`\u002Fpath\u002Finside\u002Fbucket\u002Ffile.mp4`). Persist as `inputPath`.\n\n> Note: Templates reference inputs via `inputId`. The \"Create HTTPS\"\n> path materializes the input first (returns an id); the template then\n> references that id like any other input. This keeps the\n> credential-free \u002F credential-bearing distinction at the create step\n> rather than smearing it across template rendering.\n\nDo not start Step 4 until both `inputId` and `inputPath` are captured.\n\n### Step 4 — Output (reuse or create)\n\nAsk whether to **reuse** an existing output or **create** a new one.\n\n**Reuse**: optionally run `bitmovin encoding outputs list --type s3`\n(or `gcs`, `azure`) to surface candidates. Capture the `id` from the\nuser. If you list outputs first, stop there and ask the user to choose\none before moving on. Do not start Step 5 until `outputId` is captured.\n\n**Create**: confirm provider (`s3` or `gcs`), bucket name, and that the\nrelevant env vars are set:\n\n- `s3`: `BITMOVIN_OUTPUT_ACCESS_KEY`, `BITMOVIN_OUTPUT_SECRET_KEY` (AWS keys)\n- `gcs`: `BITMOVIN_OUTPUT_ACCESS_KEY`, `BITMOVIN_OUTPUT_SECRET_KEY` (GCS\n  HMAC interoperability keys)\n\nThen run (env-var expansion only — never inline literals):\n\n```bash\nbitmovin encoding outputs create s3 \\\n  --name \"\u003CNAME>\" --bucket \"\u003CBUCKET>\" --region \"\u003CAWS_REGION>\" \\\n  --access-key \"$BITMOVIN_OUTPUT_ACCESS_KEY\" \\\n  --secret-key \"$BITMOVIN_OUTPUT_SECRET_KEY\" \\\n  --json --jq .id\n```\n\n(Use `bitmovin encoding outputs create gcs ...` for GCS — same flag\nshape, no `--region`.) Capture the printed `output_id` immediately and\ndo not start Step 5 until it has been written into the working\n`params.yaml`.\n\nNever accept access keys \u002F secret keys \u002F service-account JSON contents\nas literal CLI args or in the params file. If env vars are missing,\nstop and ask the user to export them.\n\n### Step 5 — Gather parameters\n\n*Scenarios 1–4 only. For `custom`, the template was authored in Step 2b\nand Steps 5 + 6 are skipped — proceed directly to Step 7.*\n\nAsk the user **one question at a time** with a selectable options menu (e.g.\nvia `AskUserQuestion` in Claude Code, or an equivalent picker in other\nhosts). Don't ask the user to fill out the whole `params.yaml` in one go.\n\nFor every question, present the listed options. The first option is the\ndefault — pre-select it. Always include an `Other (specify)` choice that\nfalls back to free-text input *unless the question text says otherwise*.\nOnce an answer is captured, write it to the running `params.yaml` and\nmove on to the next question.\n\nThe list below is the authoritative ordering. Ask in this order; skip any\nparameter the user has already supplied earlier in the conversation. Each\nquestion's \"applies to\" line lists which scenarios it applies to — skip the\nquestion entirely for the others.\n\n1. **encodingName** — free text. Suggest `vod-\u003Cshort-purpose>`. (all scenarios)\n2. **outputBasePath** — free text. Suggest `vod\u002F\u003CencodingName>\u002F`. (all scenarios)\n3. **outputAcl** — always ask, surface security implications. (all scenarios)\n   - `PUBLIC_READ` *(default for `per-title-h264`, `fixed-ladder-h264` —\n     anyone with the URL can play)*\n   - `PRIVATE` *(default for `av1-per-title-ugc` and `sports-clips-h264` —\n     downstream pipelines typically re-package via their own CDN; signed\n     URLs only)*\n4. **manifests** — `per-title-h264`, `fixed-ladder-h264` only.\n   `av1-per-title-ugc` emits progressive MP4 without a manifest;\n   `sports-clips-h264` hardcodes HLS-only.\n   - `[dash, hls]` *(default)*\n   - `[hls]`\n   - `[dash]`\n5. **videoLadder** — `fixed-ladder-h264` only. The per-title scenarios\n   (`per-title-h264`, `av1-per-title-ugc`) generate their own ladders;\n   `sports-clips-h264` ships a fixed 9-rendition sports playbook ladder.\n   - `360p + 720p + 1080p (default)` → `[{360,1.2M}, {720,2.4M}, {1080,4.8M}]`\n   - `240p + 480p + 720p` → `[{240,400k}, {480,1.2M}, {720,2.4M}]`\n   - `1080p only` → `[{1080,4.8M}]`\n   - `Other (specify)` — free-text JSON \u002F YAML list of `{height,bitrate}`\n6. **audioBitrate** (bps) — `per-title-h264`, `fixed-ladder-h264` only.\n   `av1-per-title-ugc` and `sports-clips-h264` are video-only.\n   - `128000` *(default)*\n   - `96000`\n   - `192000`\n   - `256000`\n7. **segmentLength** (seconds) — `per-title-h264`, `fixed-ladder-h264`,\n   `sports-clips-h264`. `av1-per-title-ugc` writes progressive MP4, not\n   segments.\n   - `4.0` *(default)*\n   - `2.0`\n   - `6.0`\n   - `Other (specify)`\n8. **encoderVersion** — these are the only valid choices; do **not**\n   offer an `Other (specify)` fallback for this question. (all scenarios)\n   - `STABLE` *(default)*\n   - `BETA`\n9. **encodingMode** — `fixed-ladder-h264` only. The per-title scenarios\n   (`per-title-h264`, `av1-per-title-ugc`) hardcode `THREE_PASS` because\n   per-title needs the analysis pass; `sports-clips-h264` lets the\n   hardware preset pick the mode.\n   - `SINGLE_PASS` *(default — fastest, lowest cost)*\n   - `TWO_PASS` *(better quality at fixed bitrate)*\n   - `THREE_PASS` *(highest quality)*\n\nAfter the last question, echo the resolved `params.yaml` back to the user\nin full and confirm before proceeding to Step 6.\n\n### Step 6 — Render template\n\n*Scenarios 1–4 only. For `custom`, the template was authored directly\nin Step 2b — skip to Step 7.*\n\nRender the chosen Jinja template into `\u003CRUN_DIR>\u002Ftemplate.yaml`:\n\n```bash\nRUN_ID=$(date -u +%Y%m%d-%H%M%S)-$(openssl rand -hex 3)\nRUN_DIR=\"$HOME\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F$RUN_ID\"\nmkdir -p \"$RUN_DIR\"\ncp params.yaml \"$RUN_DIR\u002Fparams.yaml\"\n\"$PYTHON\" -c \"\nimport jinja2, sys, yaml, pathlib\nparams = yaml.safe_load(pathlib.Path('$RUN_DIR\u002Fparams.yaml').read_text())\nenv = jinja2.Environment(\n    loader=jinja2.FileSystemLoader('\u003CSKILL_DIR>\u002Ftemplates'),\n    undefined=jinja2.StrictUndefined,\n    trim_blocks=True, lstrip_blocks=True,\n)\nout = env.get_template('\u003CTEMPLATE_NAME>.yaml.j2').render(**params)\npathlib.Path('$RUN_DIR\u002Ftemplate.yaml').write_text(out)\nprint('$RUN_DIR\u002Ftemplate.yaml')\n\"\n```\n\nShow the rendered YAML to the user (or its key sections) and confirm before\nposting.\n\n### Step 7 — Validate + start\n\nValidate the rendered YAML in two passes — schema (the CLI) and\ncross-field semantic rules (`validate_rules.py`) — then submit it. The\nCLI fetches the schema once and caches it for 24h at\n`~\u002F.config\u002Fbitmovin\u002Ftemplate-schema-v1.json`.\n\n```bash\n# 1. Schema check — structural validity, required fields, enum values.\nbitmovin encoding templates validate \"$RUN_DIR\u002Ftemplate.yaml\"\n\n# 2. Cross-field rule check — semantic constraints the schema can't\n#    express (fMP4 stream count, AV1 min bitrate, per-title bitrate\n#    algebra, hardware-encoding limits, sprite\u002Fthumbnail rules,\n#    Dolby Vision constraints). Skip only as a last resort if a rule\n#    fires that the user is sure is a false positive (the API may still\n#    reject server-side).\n\"$PYTHON\" \u003CSKILL_DIR>\u002Fscripts\u002Fvalidate_rules.py \"$RUN_DIR\u002Ftemplate.yaml\" \\\n  || { echo \"error: rule checks failed; fix the template before submitting\" >&2; exit 1; }\n\n# 3. Submit.\nENCODING_ID=$(\n  bitmovin encoding templates start \"$RUN_DIR\u002Ftemplate.yaml\" \\\n    | awk '\u002F^Encoding started:\u002F {print $3}'\n)\ntest -n \"$ENCODING_ID\" || { echo \"error: failed to capture encoding id\" >&2; exit 1; }\necho \"encoding id: $ENCODING_ID\"\n```\n\nDo **not** pass `--watch` here — Step 8 runs a defensive partial-parse\ncheck first. `--watch` would skip that and wait for terminal status\neven when the template was silently dropped.\n\nIf `templates validate` reports schema errors, or `validate_rules.py`\nprints any violations, abort and surface them to the user. For prebaked\nscenarios the structure usually points at a missing param; for `custom`,\nthe rule_id in the violation output points directly at\n`references\u002Frulebook.yaml` for the explanation.\n\n### Step 8 — Wait for `FINISHED`\n\nTwo short polling loops. Both call the Bitmovin CLI; no Python helper\nis involved.\n\n**8a — defensive partial-parse check (≈15s).** The Templates API\noccasionally returns 200 + encoding-id but silently drops sections it\ndidn't recognize (e.g. unknown top-level keys). Confirm the encoding's\n`type` settled to `VOD` before doing anything else:\n\n```bash\nDEADLINE=$(( $(date +%s) + 15 ))\nACTUAL_TYPE=\"\"\nwhile [ \"$(date +%s)\" -lt \"$DEADLINE\" ]; do\n  ACTUAL_TYPE=$(bitmovin encoding jobs get \"$ENCODING_ID\" --jq .type 2>\u002Fdev\u002Fnull | tr -d '\"')\n  [ \"$ACTUAL_TYPE\" = \"VOD\" ] && break\n  sleep 2\ndone\nif [ \"$ACTUAL_TYPE\" != \"VOD\" ]; then\n  echo \"error: Templates API silently dropped most of the template\" >&2\n  echo \"  encoding $ENCODING_ID has type='$ACTUAL_TYPE' (expected 'VOD') after 15s\" >&2\n  echo \"  inspect the rendered template at $RUN_DIR\u002Ftemplate.yaml for unknown keys\" >&2\n  exit 1\nfi\n```\n\n**8b — wait for terminal status.** VOD encodings progress\nQUEUED → RUNNING → FINISHED. Bail out on ERROR \u002F CANCELED. Default\ntimeout 120 minutes — extend for long inputs. Transient CLI errors\n(network blips, 5xx) are ignored:\n\n```bash\nDEADLINE=$(( $(date +%s) + 120 * 60 ))\nSTATUS=\"\"\nwhile [ \"$(date +%s)\" -lt \"$DEADLINE\" ]; do\n  STATUS=$(bitmovin encoding jobs status \"$ENCODING_ID\" --jq .status 2>\u002Fdev\u002Fnull | tr -d '\"')\n  case \"$STATUS\" in\n    FINISHED) break ;;\n    ERROR|CANCELED|TRANSFER_ERROR) echo \"error: encoding $ENCODING_ID reached terminal status $STATUS\" >&2; exit 1 ;;\n  esac\n  sleep 15\ndone\n[ \"$STATUS\" = \"FINISHED\" ] || { echo \"error: timed out after 120 min waiting for FINISHED\" >&2; exit 1; }\n\necho\necho \"Dashboard:    https:\u002F\u002Fdashboard.bitmovin.com\u002Fencoding\u002Fencodings\u002F$ENCODING_ID\"\necho \"Output base:  \u003CoutputBasePath from params> (manifests are listed in the dashboard)\"\n```\n\nManifest URL synthesis is delegated to the dashboard — the rendered\noutput paths plus per-bucket conventions are easier to surface there\nthan to reconstruct in the shell. The user can also call\n`bitmovin encoding manifests list --type dash` and `--type hls` for\nthe manifest IDs and use `bitmovin encoding manifests get \u003Cid> --type\n\u003Cdash|hls>` to inspect details.\n\n### After it finishes\n\nThe encoding is now done; output files are in the bucket. The encoding\nrecord stays in the account so the user can inspect logs, statistics,\nand re-export manifests via the dashboard. There is no \"stop\" step for\nVOD — it has already terminated.\n\nFor an ad-hoc status check at any point, use the CLI directly:\n\n```bash\nbitmovin encoding jobs status \"$ENCODING_ID\"\n```\n\n## Safety Rules\n\n- Never log `BITMOVIN_API_KEY`, `BITMOVIN_OUTPUT_ACCESS_KEY`,\n  `BITMOVIN_OUTPUT_SECRET_KEY`, or any value resembling a secret.\n- Never accept credentials as literal CLI args or in `params.yaml`. The\n  Bitmovin CLI's `outputs create` requires `--access-key` \u002F\n  `--secret-key` flags — pass these only via shell env-var expansion\n  (`--access-key \"$BITMOVIN_OUTPUT_ACCESS_KEY\"`) so the literal value\n  never appears in scripts, history, or rendered templates.\n- Never write secrets into the rendered template.\n- If a user pastes a secret into the prompt, refuse to use it; tell\n  them to export it as an env var instead.\n- Inputs that need credentials (S3\u002FGCS\u002FAzure\u002FSFTP\u002F...) MUST be reused\n  via an existing `inputId`. The skill only creates HTTP\u002FHTTPS inputs.\n","# Bitmovin VOD Encoding Skill\n\nWalks the user through configuring and starting a Bitmovin VOD encoding.\nThe heavy lifting is done by the Bitmovin **Encoding Templates API**: a\nsingle `POST \u002Fencoding\u002Ftemplates\u002Fstart` creates inputs, codec configs,\nencoding, streams, muxings, manifests **and** starts the encoding from\none YAML document.\n\nThis skill renders that YAML from a small parameter file, validates and\nsubmits it via the **Bitmovin CLI** (`bitmovin encoding ...`), polls\nuntil the encoder reaches `FINISHED`, and points the user at the\ndashboard to grab manifest URLs.\n\n## Prerequisites\n\n- **Bitmovin CLI** (`@bitmovin\u002Fcli`, ≥ 0.2.0) — drives `inputs list\u002Fcreate`,\n  `outputs list\u002Fcreate`, `templates validate`, `templates start`,\n  `jobs get`, `jobs status`. Install with `npm install -g @bitmovin\u002Fcli`.\n- **Python ≥ 3.10** — Step 1's `scripts\u002Fensure_venv.sh` auto-creates a\n  dedicated venv and installs `pyyaml` and `jinja2` into it if they\n  aren't already importable from the user's `python3`. Used only by the\n  inline Jinja render block in Step 6 and by `validate_rules.py` in\n  Step 7; every other workflow step is the CLI.\n- `BITMOVIN_API_KEY` environment variable set.\n- For creating a new output (optional): `BITMOVIN_OUTPUT_ACCESS_KEY` \u002F\n  `BITMOVIN_OUTPUT_SECRET_KEY` env vars (see Step 4). Credentials are\n  read from the environment and passed to the CLI via shell expansion at\n  invocation time — never hardcoded into scripts, the params file, or\n  the rendered template.\n\nThe skill never embeds secrets in the rendered template or log output.\nInputs that need credentials (S3, GCS, Azure, …) must be **reused** via\nan existing input id — they are never created from this skill, since\nthat would require pasting credentials into a parameter file.\n\n## Path Conventions\n\n- `SKILL_DIR`: install location of this skill (e.g.\n  `~\u002F.claude\u002Fskills\u002Fbitmovin-encoding-vod` or\n  `~\u002F.codex\u002Fskills\u002Fbitmovin-encoding-vod`). Used to locate `scripts\u002F` and\n  `templates\u002F`.\n- `RUN_DIR`: per-run cache directory at\n  `~\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F\u003Crun-id>\u002F`, where `\u003Crun-id>` is\n  `YYYYMMDD-HHMMSS-\u003Cshort-hash>`. Holds the rendered template and a copy\n  of the params file. RUN_DIR MUST stay outside the skill directory so\n  its contents are never published or installed.\n\n## Scripts\n\n| Script | Purpose |\n|---|---|\n| `scripts\u002Fensure_venv.sh` | Prints the path to a Python interpreter that has `pyyaml` and `jinja2` available. Uses the user's `python3` if it already has them; otherwise creates \u002F reuses a venv at `~\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F.venv\u002F` and installs the deps there. |\n| `scripts\u002Fvalidate_rules.py \u003Ctemplate.yaml>` | Runs cross-field rule checks (see `references\u002Frulebook.yaml`) against a rendered Encoding Template. Catches semantic errors the JSON schema can't express — fMP4-stream-count, AV1 min bitrate (with per-title carve-out), per-title bitrate algebra, hardware-encoding limits, sprite\u002Fthumbnail rules, Dolby Vision constraints. Exits non-zero on violations. Always run between `bitmovin encoding templates validate` and `bitmovin encoding templates start`. |\n\nAll other workflow steps — input listing \u002F creation, output listing \u002F\ncreation, template validation \u002F submission, status polling — are driven\ndirectly by the Bitmovin CLI from the inline shell snippets in this\ndocument. SKILL.md is responsible for prompting the user.\n\n## References\n\n| File | Purpose |\n|---|---|\n| `references\u002Frulebook.yaml` | Cross-field semantic rules for VOD encodings, derived from Bitmovin's server-side validators. Each rule has an `id`, a `rule` description, and an `applies_when` predicate. Consulted during the custom-build flow (Step 2b) to prune options the API would reject; enforced post-render by `validate_rules.py`. |\n\n## Templates\n\nJinja2 templates in `\u003CSKILL_DIR>\u002Ftemplates\u002F`:\n\n| Template | Use case |\n|---|---|\n| `per-title-h264.yaml.j2` | H.264 Per-Title encoding — Bitmovin's algorithm picks an optimal bitrate ladder per input. Includes a 1080p fixed-resolution anchor so the ladder always reaches HD when the source supports it. THREE_PASS encoding. Default DASH + HLS manifests. |\n| `fixed-ladder-h264.yaml.j2` | H.264 fixed bitrate ladder — encode the renditions you specify in `videoLadder`. Predictable output sizes, fast encode (single-pass by default). Default DASH + HLS manifests. |\n| `av1-per-title-ugc.yaml.j2` | AV1 Per-Title for viral \u002F UGC pipelines — ~50% bitrate savings vs H.264. Emits a progressive MP4 file per rendition (no fmp4 segments, no DASH\u002FHLS manifest), video-only. Includes a 1080p fixed-resolution anchor. THREE_PASS encoding. |\n| `sports-clips-h264.yaml.j2` | H.264 sports-clips workflow optimized for time-to-publish — NVIDIA-GPU-backed `VOD_HARDWARE_SHORTFORM` preset, 9-rendition ladder (360p–1080p with multi-bitrate steps at 540p\u002F720p\u002F1080p), HLS-only with explicit per-rendition manifest config. Pinned to `cloudRegion: AWS_EU_WEST_1` (required for the hardware preset). Video-only, ACL=PRIVATE by default. |\n\nThe H.264 per-title \u002F fixed-ladder templates produce CMAF-style fmp4\nwith default DASH+HLS manifests. The AV1 UGC template produces\nprogressive MP4 files without manifests. The sports-clips template\nproduces fmp4 with HLS-only manifests and uses a hardcoded ladder.\nCustomers can hand-edit the rendered YAML before\n`bitmovin encoding templates start` if they need variants (more\nrenditions, different segment naming, additional muxing types).\n\n`\u003CSKILL_DIR>\u002Fexamples\u002Fparams.example.yaml` documents every parameter.\n\n## Workflow\n\n### Step 1 — Verify prerequisites\n\nConfirm the Bitmovin CLI is installed and resolve the Python interpreter\nthat has the runtime deps (used by Steps 6 and 7):\n\n```bash\ncommand -v bitmovin >\u002Fdev\u002Fnull \\\n  || { echo \"error: bitmovin CLI not found. Install with: npm install -g @bitmovin\u002Fcli\" >&2; exit 1; }\nPYTHON=$(bash \u003CSKILL_DIR>\u002Fscripts\u002Fensure_venv.sh) || exit 1\ntest -n \"$BITMOVIN_API_KEY\" || { echo \"error: BITMOVIN_API_KEY is not set\" >&2; exit 1; }\necho \"OK ($PYTHON)\"\n```\n\n`$PYTHON` is reused in Steps 6 and 7. If `BITMOVIN_API_KEY` is empty,\nask the user to export it before continuing. The CLI reads the key from\nthe same env var, so no extra config is required.\n\nIf `python3` itself is missing, `ensure_venv.sh` prints a clear error\nand exits non-zero — point the user at https:\u002F\u002Fwww.python.org\u002Fdownloads\u002F\n(Python ≥ 3.10).\n\n### Step 2 — Pick scenario\n\nAsk the user which template to use. These are the only valid choices —\ndo **not** offer an `Other (specify)` free-text fallback. The fifth\noption is the explicit escape hatch:\n\n1. `per-title-h264` — H.264 Per-Title (default; let the algorithm pick the ladder)\n2. `fixed-ladder-h264` — H.264 fixed ladder (you specify the renditions)\n3. `av1-per-title-ugc` — AV1 Per-Title for UGC pipelines (progressive MP4, no manifests, ~50% bitrate savings vs H.264)\n4. `sports-clips-h264` — H.264 sports clips with NVIDIA hardware acceleration (VOD_HARDWARE_SHORTFORM preset, HLS-only, hardcoded sports ladder, time-to-publish optimized)\n5. `custom` — none of the above fits; describe the use case in free text and the skill assembles a template from the schema + rulebook (see Step 2b)\n\nFor options 1–4, map to the matching template under\n`\u003CSKILL_DIR>\u002Ftemplates\u002F`. For option 5, jump to **Step 2b** before Step 3.\n\n### Step 2b — Custom Build (only when scenario = `custom`)\n\nThe user has described a use case the four prebaked scenarios don't fit.\nThe skill guides them through assembling a template from primitives,\nfiltering options at each decision using the cross-field rulebook so\nchoices that the API would reject never appear.\n\n**Sources of truth, in order of authority:**\n\n1. `\u003CSKILL_DIR>\u002Freferences\u002Frulebook.yaml` — semantic compatibility rules\n   derived from Bitmovin's server-side validators. Each rule has an\n   `applies_when` predicate; if it matches the user's choices, apply the\n   rule's constraint. Every rule applies to VOD (live-only rules have\n   been removed).\n2. `~\u002F.config\u002Fbitmovin\u002Ftemplate-schema-v1.json` — the published Encoding\n   Template JSON Schema (24h-cached by `bitmovin encoding templates\n   validate`). Use it to discover allowed values for enum fields\n   (codecs, profiles, manifest types, DRM types, ACL permissions, …).\n   If the cache is missing, run `bitmovin encoding templates validate`\n   against any prebaked template once to warm it, or fall back to the\n   four existing templates as worked examples.\n3. `\u003CSKILL_DIR>\u002Ftemplates\u002F*.yaml.j2` — worked examples of valid template\n   shapes. Read at least one matching the user's container choice\n   (fmp4 \u002F progressive mp4 \u002F hls-only) before authoring.\n\n**Workflow:**\n\n1. **Capture the use case.** Take the user's free-text description.\n   Re-state your understanding back in one sentence and confirm before\n   continuing.\n\n2. **Walk a decision tree.** Ask **one question at a time** with a\n   selectable picker. After each answer, consult the rulebook: drop any\n   downstream option whose `applies_when` would conflict with the\n   answers so far. Order:\n\n   a. **Video codec(s)** — h264 (broadest device support), h265\n      (~50% bandwidth savings), av1 (~50% savings, newer; rule\n      `codec.av1.min_bitrate` requires bitrate ≥ 10000 unless\n      per-title). Multi-codec ladders allowed.\n   b. **Encoding strategy** — per-title (algorithm-driven ladder, runs\n      THREE_PASS), fixed ladder (renditions you list), single rendition.\n   c. **Audio** — AAC (default), Dolby Atmos \u002F DD+ (rule\n      `dd.drm_encoder_features` gates with DRM; rule `dd.invalid_filters`\n      blocks AUDIO_VOLUME \u002F WATERMARK \u002F ENHANCED_WATERMARK), pass-through,\n      or none (video-only).\n   d. **Muxing format** — fmp4 (CMAF-style; works with DASH and HLS;\n      rule `muxing.fmp4.exactly_one_stream` means one muxing per\n      stream), progressive MP4 (single file, no manifest), TS, CMAF.\n      For fmp4 + AV1, rule `muxing.mp4_fragmented.av1_manifest_type`\n      restricts manifest type to DASH_ON_DEMAND or NONE.\n   e. **Manifest format** — DASH only, HLS only, both, none. Default-API\n      manifests (`defaultapi.\u003Cid>`) are simpler than custom; prefer them\n      unless the user needs custom adaptation sets.\n   f. **DRM** (optional) — none (default), Widevine, PlayReady, FairPlay,\n      multi-DRM via CencDrm. Rulebook gates: `drm.fmp4.fairplay_codec`\n      requires HEVC for fmp4+FairPlay unless encoder version supports\n      `FIXED_ENCRYPTION_METHOD_SELECTION`.\n   g. **HDR \u002F Dolby Vision** (optional) — none (default), HDR10, Dolby\n      Vision. DV pulls in many rules (`dv.input_codec_allowlist` →\n      H.264\u002FH.265 only, `dv.muxing_audio_codec_allowlist` → AAC\u002FAtmos\n      audio, `dv.pixel_format` → YUV420P10LE, `dv.bufsize_maxrate_required`\n      except per-title which uses `dv.per_title_factors_required`).\n      Walk these explicitly with the user.\n   h. **Hardware acceleration** (optional) — none (default), or NVIDIA\n      preset. Hardware encoding pulls in rules `hw.vod_only`,\n      `hw.aws_only`, `hw.no_per_title`, `hw.no_dolby_vision`,\n      `hw.no_filters`, `hw.no_thumbnails`, `hw.no_psnr`, etc. — if the\n      user already chose per-title or DV, hardware is no longer offered.\n   i. **Out-of-scope features** — sprites, subtitles (CEA \u002F WebVTT \u002F\n      IMSC), filters (watermark \u002F scale \u002F crop), SCTE-35,\n      concatenation, multi-period DASH. If the user needs any of\n      these, point them at https:\u002F\u002Fdeveloper.bitmovin.com\u002Fencoding\u002Fdocs\n      and stop the custom build (the rulebook covers some of these but\n      the skill does not yet author the YAML for them).\n\n3. **Author the YAML.** Once the decision tree is complete, write\n   `$RUN_DIR\u002Ftemplate.yaml` directly. Use the prebaked templates as\n   structural examples. Required top-level keys: `metadata` (with\n   `type: VOD`), `configurations`, `encodings`, optionally `manifests`.\n   Reference inputs\u002Foutputs by id (Steps 3 + 4). Show the assembled\n   YAML to the user and confirm before continuing.\n\n4. **Rejoin Step 7.** Skip Steps 5 (gather params) and 6 (render\n   template) — the YAML is already authored. Step 7 runs\n   `bitmovin encoding templates validate` plus `validate_rules.py`, so\n   if any rulebook constraint was missed during the decision tree, it\n   surfaces as a violation before the submit.\n\nIf, during the decision tree, the user picks a combination that the\nrulebook says is impossible (e.g. hardware + per-title), stop, explain\nwhich rule blocks it (cite `rule.id`), and ask the user to revisit the\nprior decision.\n\n### Step 3 — Input source\n\nAsk whether to **reuse** an existing input or **create** a fresh HTTPS\ninput. The skill never accepts credentials, so for S3\u002FGCS\u002FAzure the\ninput must already exist in the account.\n\n**Reuse**: optionally run `bitmovin encoding inputs list --type s3`\n(filter with `--type https`, `--type gcs`, etc. if the user knows the\ntype) to surface candidates. Capture the `id` from the user. Persist it\nas `inputId` in the working `params.yaml`.\n\n**Create HTTPS**: ask for the host (no scheme, no path — e.g.\n`bitmovin-sample-content.s3.eu-west-1.amazonaws.com`) and a name. Then\nrun:\n\n```bash\nbitmovin encoding inputs create https \\\n  --name \"\u003CNAME>\" --host \"\u003CHOST>\" \\\n  --json --jq .id\n```\n\nIt prints the new `input_id`. Persist it as `inputId` in `params.yaml`.\n\nIn **both** cases, also ask for `inputPath` — the path to the input file\n*inside* the input source (e.g. `\u002Fsintel\u002Fsintel.mp4` or\n`\u002Fpath\u002Finside\u002Fbucket\u002Ffile.mp4`). Persist as `inputPath`.\n\n> Note: Templates reference inputs via `inputId`. The \"Create HTTPS\"\n> path materializes the input first (returns an id); the template then\n> references that id like any other input. This keeps the\n> credential-free \u002F credential-bearing distinction at the create step\n> rather than smearing it across template rendering.\n\nDo not start Step 4 until both `inputId` and `inputPath` are captured.\n\n### Step 4 — Output (reuse or create)\n\nAsk whether to **reuse** an existing output or **create** a new one.\n\n**Reuse**: optionally run `bitmovin encoding outputs list --type s3`\n(or `gcs`, `azure`) to surface candidates. Capture the `id` from the\nuser. If you list outputs first, stop there and ask the user to choose\none before moving on. Do not start Step 5 until `outputId` is captured.\n\n**Create**: confirm provider (`s3` or `gcs`), bucket name, and that the\nrelevant env vars are set:\n\n- `s3`: `BITMOVIN_OUTPUT_ACCESS_KEY`, `BITMOVIN_OUTPUT_SECRET_KEY` (AWS keys)\n- `gcs`: `BITMOVIN_OUTPUT_ACCESS_KEY`, `BITMOVIN_OUTPUT_SECRET_KEY` (GCS\n  HMAC interoperability keys)\n\nThen run (env-var expansion only — never inline literals):\n\n```bash\nbitmovin encoding outputs create s3 \\\n  --name \"\u003CNAME>\" --bucket \"\u003CBUCKET>\" --region \"\u003CAWS_REGION>\" \\\n  --access-key \"$BITMOVIN_OUTPUT_ACCESS_KEY\" \\\n  --secret-key \"$BITMOVIN_OUTPUT_SECRET_KEY\" \\\n  --json --jq .id\n```\n\n(Use `bitmovin encoding outputs create gcs ...` for GCS — same flag\nshape, no `--region`.) Capture the printed `output_id` immediately and\ndo not start Step 5 until it has been written into the working\n`params.yaml`.\n\nNever accept access keys \u002F secret keys \u002F service-account JSON contents\nas literal CLI args or in the params file. If env vars are missing,\nstop and ask the user to export them.\n\n### Step 5 — Gather parameters\n\n*Scenarios 1–4 only. For `custom`, the template was authored in Step 2b\nand Steps 5 + 6 are skipped — proceed directly to Step 7.*\n\nAsk the user **one question at a time** with a selectable options menu (e.g.\nvia `AskUserQuestion` in Claude Code, or an equivalent picker in other\nhosts). Don't ask the user to fill out the whole `params.yaml` in one go.\n\nFor every question, present the listed options. The first option is the\ndefault — pre-select it. Always include an `Other (specify)` choice that\nfalls back to free-text input *unless the question text says otherwise*.\nOnce an answer is captured, write it to the running `params.yaml` and\nmove on to the next question.\n\nThe list below is the authoritative ordering. Ask in this order; skip any\nparameter the user has already supplied earlier in the conversation. Each\nquestion's \"applies to\" line lists which scenarios it applies to — skip the\nquestion entirely for the others.\n\n1. **encodingName** — free text. Suggest `vod-\u003Cshort-purpose>`. (all scenarios)\n2. **outputBasePath** — free text. Suggest `vod\u002F\u003CencodingName>\u002F`. (all scenarios)\n3. **outputAcl** — always ask, surface security implications. (all scenarios)\n   - `PUBLIC_READ` *(default for `per-title-h264`, `fixed-ladder-h264` —\n     anyone with the URL can play)*\n   - `PRIVATE` *(default for `av1-per-title-ugc` and `sports-clips-h264` —\n     downstream pipelines typically re-package via their own CDN; signed\n     URLs only)*\n4. **manifests** — `per-title-h264`, `fixed-ladder-h264` only.\n   `av1-per-title-ugc` emits progressive MP4 without a manifest;\n   `sports-clips-h264` hardcodes HLS-only.\n   - `[dash, hls]` *(default)*\n   - `[hls]`\n   - `[dash]`\n5. **videoLadder** — `fixed-ladder-h264` only. The per-title scenarios\n   (`per-title-h264`, `av1-per-title-ugc`) generate their own ladders;\n   `sports-clips-h264` ships a fixed 9-rendition sports playbook ladder.\n   - `360p + 720p + 1080p (default)` → `[{360,1.2M}, {720,2.4M}, {1080,4.8M}]`\n   - `240p + 480p + 720p` → `[{240,400k}, {480,1.2M}, {720,2.4M}]`\n   - `1080p only` → `[{1080,4.8M}]`\n   - `Other (specify)` — free-text JSON \u002F YAML list of `{height,bitrate}`\n6. **audioBitrate** (bps) — `per-title-h264`, `fixed-ladder-h264` only.\n   `av1-per-title-ugc` and `sports-clips-h264` are video-only.\n   - `128000` *(default)*\n   - `96000`\n   - `192000`\n   - `256000`\n7. **segmentLength** (seconds) — `per-title-h264`, `fixed-ladder-h264`,\n   `sports-clips-h264`. `av1-per-title-ugc` writes progressive MP4, not\n   segments.\n   - `4.0` *(default)*\n   - `2.0`\n   - `6.0`\n   - `Other (specify)`\n8. **encoderVersion** — these are the only valid choices; do **not**\n   offer an `Other (specify)` fallback for this question. (all scenarios)\n   - `STABLE` *(default)*\n   - `BETA`\n9. **encodingMode** — `fixed-ladder-h264` only. The per-title scenarios\n   (`per-title-h264`, `av1-per-title-ugc`) hardcode `THREE_PASS` because\n   per-title needs the analysis pass; `sports-clips-h264` lets the\n   hardware preset pick the mode.\n   - `SINGLE_PASS` *(default — fastest, lowest cost)*\n   - `TWO_PASS` *(better quality at fixed bitrate)*\n   - `THREE_PASS` *(highest quality)*\n\nAfter the last question, echo the resolved `params.yaml` back to the user\nin full and confirm before proceeding to Step 6.\n\n### Step 6 — Render template\n\n*Scenarios 1–4 only. For `custom`, the template was authored directly\nin Step 2b — skip to Step 7.*\n\nRender the chosen Jinja template into `\u003CRUN_DIR>\u002Ftemplate.yaml`:\n\n```bash\nRUN_ID=$(date -u +%Y%m%d-%H%M%S)-$(openssl rand -hex 3)\nRUN_DIR=\"$HOME\u002F.cache\u002Fbitmovin\u002Fbitmovin-encoding-vod\u002F$RUN_ID\"\nmkdir -p \"$RUN_DIR\"\ncp params.yaml \"$RUN_DIR\u002Fparams.yaml\"\n\"$PYTHON\" -c \"\nimport jinja2, sys, yaml, pathlib\nparams = yaml.safe_load(pathlib.Path('$RUN_DIR\u002Fparams.yaml').read_text())\nenv = jinja2.Environment(\n    loader=jinja2.FileSystemLoader('\u003CSKILL_DIR>\u002Ftemplates'),\n    undefined=jinja2.StrictUndefined,\n    trim_blocks=True, lstrip_blocks=True,\n)\nout = env.get_template('\u003CTEMPLATE_NAME>.yaml.j2').render(**params)\npathlib.Path('$RUN_DIR\u002Ftemplate.yaml').write_text(out)\nprint('$RUN_DIR\u002Ftemplate.yaml')\n\"\n```\n\nShow the rendered YAML to the user (or its key sections) and confirm before\nposting.\n\n### Step 7 — Validate + start\n\nValidate the rendered YAML in two passes — schema (the CLI) and\ncross-field semantic rules (`validate_rules.py`) — then submit it. The\nCLI fetches the schema once and caches it for 24h at\n`~\u002F.config\u002Fbitmovin\u002Ftemplate-schema-v1.json`.\n\n```bash\n# 1. Schema check — structural validity, required fields, enum values.\nbitmovin encoding templates validate \"$RUN_DIR\u002Ftemplate.yaml\"\n\n# 2. Cross-field rule check — semantic constraints the schema can't\n#    express (fMP4 stream count, AV1 min bitrate, per-title bitrate\n#    algebra, hardware-encoding limits, sprite\u002Fthumbnail rules,\n#    Dolby Vision constraints). Skip only as a last resort if a rule\n#    fires that the user is sure is a false positive (the API may still\n#    reject server-side).\n\"$PYTHON\" \u003CSKILL_DIR>\u002Fscripts\u002Fvalidate_rules.py \"$RUN_DIR\u002Ftemplate.yaml\" \\\n  || { echo \"error: rule checks failed; fix the template before submitting\" >&2; exit 1; }\n\n# 3. Submit.\nENCODING_ID=$(\n  bitmovin encoding templates start \"$RUN_DIR\u002Ftemplate.yaml\" \\\n    | awk '\u002F^Encoding started:\u002F {print $3}'\n)\ntest -n \"$ENCODING_ID\" || { echo \"error: failed to capture encoding id\" >&2; exit 1; }\necho \"encoding id: $ENCODING_ID\"\n```\n\nDo **not** pass `--watch` here — Step 8 runs a defensive partial-parse\ncheck first. `--watch` would skip that and wait for terminal status\neven when the template was silently dropped.\n\nIf `templates validate` reports schema errors, or `validate_rules.py`\nprints any violations, abort and surface them to the user. For prebaked\nscenarios the structure usually points at a missing param; for `custom`,\nthe rule_id in the violation output points directly at\n`references\u002Frulebook.yaml` for the explanation.\n\n### Step 8 — Wait for `FINISHED`\n\nTwo short polling loops. Both call the Bitmovin CLI; no Python helper\nis involved.\n\n**8a — defensive partial-parse check (≈15s).** The Templates API\noccasionally returns 200 + encoding-id but silently drops sections it\ndidn't recognize (e.g. unknown top-level keys). Confirm the encoding's\n`type` settled to `VOD` before doing anything else:\n\n```bash\nDEADLINE=$(( $(date +%s) + 15 ))\nACTUAL_TYPE=\"\"\nwhile [ \"$(date +%s)\" -lt \"$DEADLINE\" ]; do\n  ACTUAL_TYPE=$(bitmovin encoding jobs get \"$ENCODING_ID\" --jq .type 2>\u002Fdev\u002Fnull | tr -d '\"')\n  [ \"$ACTUAL_TYPE\" = \"VOD\" ] && break\n  sleep 2\ndone\nif [ \"$ACTUAL_TYPE\" != \"VOD\" ]; then\n  echo \"error: Templates API silently dropped most of the template\" >&2\n  echo \"  encoding $ENCODING_ID has type='$ACTUAL_TYPE' (expected 'VOD') after 15s\" >&2\n  echo \"  inspect the rendered template at $RUN_DIR\u002Ftemplate.yaml for unknown keys\" >&2\n  exit 1\nfi\n```\n\n**8b — wait for terminal status.** VOD encodings progress\nQUEUED → RUNNING → FINISHED. Bail out on ERROR \u002F CANCELED. Default\ntimeout 120 minutes — extend for long inputs. Transient CLI errors\n(network blips, 5xx) are ignored:\n\n```bash\nDEADLINE=$(( $(date +%s) + 120 * 60 ))\nSTATUS=\"\"\nwhile [ \"$(date +%s)\" -lt \"$DEADLINE\" ]; do\n  STATUS=$(bitmovin encoding jobs status \"$ENCODING_ID\" --jq .status 2>\u002Fdev\u002Fnull | tr -d '\"')\n  case \"$STATUS\" in\n    FINISHED) break ;;\n    ERROR|CANCELED|TRANSFER_ERROR) echo \"error: encoding $ENCODING_ID reached terminal status $STATUS\" >&2; exit 1 ;;\n  esac\n  sleep 15\ndone\n[ \"$STATUS\" = \"FINISHED\" ] || { echo \"error: timed out after 120 min waiting for FINISHED\" >&2; exit 1; }\n\necho\necho \"Dashboard:    https:\u002F\u002Fdashboard.bitmovin.com\u002Fencoding\u002Fencodings\u002F$ENCODING_ID\"\necho \"Output base:  \u003CoutputBasePath from params> (manifests are listed in the dashboard)\"\n```\n\nManifest URL synthesis is delegated to the dashboard — the rendered\noutput paths plus per-bucket conventions are easier to surface there\nthan to reconstruct in the shell. The user can also call\n`bitmovin encoding manifests list --type dash` and `--type hls` for\nthe manifest IDs and use `bitmovin encoding manifests get \u003Cid> --type\n\u003Cdash|hls>` to inspect details.\n\n### After it finishes\n\nThe encoding is now done; output files are in the bucket. The encoding\nrecord stays in the account so the user can inspect logs, statistics,\nand re-export manifests via the dashboard. There is no \"stop\" step for\nVOD — it has already terminated.\n\nFor an ad-hoc status check at any point, use the CLI directly:\n\n```bash\nbitmovin encoding jobs status \"$ENCODING_ID\"\n```\n\n## Safety Rules\n\n- Never log `BITMOVIN_API_KEY`, `BITMOVIN_OUTPUT_ACCESS_KEY`,\n  `BITMOVIN_OUTPUT_SECRET_KEY`, or any value resembling a secret.\n- Never accept credentials as literal CLI args or in `params.yaml`. The\n  Bitmovin CLI's `outputs create` requires `--access-key` \u002F\n  `--secret-key` flags — pass these only via shell env-var expansion\n  (`--access-key \"$BITMOVIN_OUTPUT_ACCESS_KEY\"`) so the literal value\n  never appears in scripts, history, or rendered templates.\n- Never write secrets into the rendered template.\n- If a user pastes a secret into the prompt, refuse to use it; tell\n  them to export it as an env var instead.\n- Inputs that need credentials (S3\u002FGCS\u002FAzure\u002FSFTP\u002F...) MUST be reused\n  via an existing `inputId`. The skill only creates HTTP\u002FHTTPS inputs.\n",{"name":5,"description":7},"main","14b211bb07d3e4057b85fb9140369fc73b1eb33b","skills\u002Fbitmovin-encoding-vod","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills","https:\u002F\u002Fgithub.com\u002Fbitmovin","https:\u002F\u002Fbitmovin.com","2026-11-12 23:46:20",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add bitmovin\u002Fskills --skill bitmovin-encoding-vod",{"tool":56,"command":57},"bunx","bunx skills add bitmovin\u002Fskills --skill bitmovin-encoding-vod",{"tool":59,"command":60},"pnpm","pnpm dlx skills add bitmovin\u002Fskills --skill bitmovin-encoding-vod","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002FSKILL.md",true,[64,70,74,78,84,88,94,98,102],{"path":65,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":68,"sourceHtmlUrl":69},"examples\u002Fparams.example.yaml","REFERENCE","参考文档",2859,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Fexamples\u002Fparams.example.yaml",{"path":71,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":72,"sourceHtmlUrl":73},"README.md",7078,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002FREADME.md",{"path":75,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":76,"sourceHtmlUrl":77},"references\u002Frulebook.yaml",15145,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Freferences\u002Frulebook.yaml",{"path":79,"resourceType":80,"resourceTypeDesc":81,"sizeBytes":82,"sourceHtmlUrl":83},"scripts\u002Fensure_venv.sh","SCRIPT","脚本",2113,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Fscripts\u002Fensure_venv.sh",{"path":85,"resourceType":80,"resourceTypeDesc":81,"sizeBytes":86,"sourceHtmlUrl":87},"scripts\u002Fvalidate_rules.py",33685,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Fscripts\u002Fvalidate_rules.py",{"path":89,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":92,"sourceHtmlUrl":93},"templates\u002Fav1-per-title-ugc.yaml.j2","OTHER","其他",3074,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Ftemplates\u002Fav1-per-title-ugc.yaml.j2",{"path":95,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":96,"sourceHtmlUrl":97},"templates\u002Ffixed-ladder-h264.yaml.j2",4449,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Ftemplates\u002Ffixed-ladder-h264.yaml.j2",{"path":99,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":100,"sourceHtmlUrl":101},"templates\u002Fper-title-h264.yaml.j2",5335,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Ftemplates\u002Fper-title-h264.yaml.j2",{"path":103,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":104,"sourceHtmlUrl":105},"templates\u002Fsports-clips-h264.yaml.j2",4582,"https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-encoding-vod\u002Ftemplates\u002Fsports-clips-h264.yaml.j2",[107,137,162,184,204,226],{"skillNo":108,"name":9,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":120,"publishedAt":38},"01M6XCZ365TGD9DCJG6Z45S0T4","Hub skill for Bitmovin video infrastructure. Use when the user mentions Bitmovin, asks about video playback, encoding, transcoding, streaming, player integration, video analytics, content delivery optimization, or video AI. Routes to the right Bitmovin product (Player, VOD\u002FLive Encoding, Observability, AI Scene Analysis, Streams, Stream Lab) and walks through MCP\u002FCLI\u002FSDK setup.","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin\u002FSKILL.md",[112,117],{"categoryNo":113,"categoryName":114,"taxonomyType":115,"taxonomyTypeDesc":116},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",{"categoryNo":118,"categoryName":119,"taxonomyType":115,"taxonomyTypeDesc":116},"01JBSEEDCAT000000000000023","Skill与智能体开发",[9,121,22,122,123,124,125,126,127,128,129,35,130,131,132,133,134,135,27,136],"MCP","analytics","infrastructure","product","observability","streaming","Optimization","analysis","Video","sdk setup","delivery","live","streams","lab","player","when",{"skillNo":138,"name":139,"nameZh":6,"description":140,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":141,"categories":142,"keywords":146,"publishedAt":38},"01M6XCYXP57QRYXCW7QN1HXNVC","bitmovin-player-web","Integrate the Bitmovin Web Player SDK into a web app. Use when the user asks to add video playback, embed a player, play HLS\u002FDASH\u002FMP4\u002FWHEP\u002FMOQ, set up DRM (Widevine\u002FPlayReady\u002FFairPlay), integrate ads, customize the Player UI, or work with the Bitmovin Player in any way. Covers both Player v8 (stable) and Player Web X \u002F PWX (next-gen).","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-player-web\u002FSKILL.md",[143],{"categoryNo":144,"categoryName":145,"taxonomyType":115,"taxonomyTypeDesc":116},"01JBSEEDCAT000000000000009","前端开发",[147,135,148,9,149,150,151,129,152,153,154,35,155,156,157,158,159,160,161,136],"web","bitmovin player web","play","ui","SET","ads","mp4","work","integrate","up","next","app","add","dash","hls",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":38},"01M6XCYRHQ60DC0YXWRCASET1X","bitmovin-player-ios","Integrate and troubleshoot the Bitmovin Player SDK for iOS, tvOS, and visionOS in Swift, SwiftUI, UIKit, and existing Objective-C apps, including playback setup, player lifecycle, source loading, DRM, ads, AirPlay, Google Cast \u002F Chromecast, PiP, platform-specific UX, logs, network diagnostics, and stream validation.","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-player-ios\u002FSKILL.md",[],[169,135,170,9,171,172,173,174,175,152,176,177,155,178,179,180,27,181,182,183],"ios","bitmovin player ios","google","swift","validation","logs","lifecycle","swiftui","uikit","platform","apps","pip","Existing","stream","objective",{"skillNo":185,"name":186,"nameZh":6,"description":187,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":188,"categories":189,"keywords":190,"publishedAt":38},"01M6XCYM297KGT0QKD7J9DNC4G","bitmovin-player-android","Integrate and troubleshoot the Bitmovin Android Player SDK in Kotlin\u002FCompose Android apps, including playback setup, Web UI, PiP\u002Ffullscreen handlers, media session, cast, TV variants, and source-loading robustness.","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-player-android\u002FSKILL.md",[],[191,135,192,9,193,147,150,194,195,196,155,197,198,179,199,200,180,201,202,203],"android","bitmovin player android","troubleshoot","Media","kotlin","session","compose","cast","web ui","loading","source","robustness","variants",{"skillNo":205,"name":206,"nameZh":6,"description":207,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":208,"categories":209,"keywords":211,"publishedAt":38},"01M6XCYCHP945BKSJ37BMDR0KR","bitmovin-observability-root-cause-analysis","Root-cause analysis for a video QoE metric that moved — startup time, rebuffer ratio, error rate, bitrate, video-start-failures — using the Bitmovin Observability MCP. Use whenever someone asks WHY a QoE metric changed, spiked, dropped, regressed, or \"looks off\", whether a release or CDN change hurt quality, or what drives a delta between two windows or cohorts. Trigger even without \"RCA\" — \"rebuffering is up in APAC\", \"did v11 regress startup?\", \"what happened to error rate Tuesday\" all belong here. Drives a disciplined Define→Gather→Reflect→Conclude investigation with mix-vs-rate (Simpson's paradox) protection and a falsification step, producing a structured findings object.","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-observability-root-cause-analysis\u002FSKILL.md",[210],{"categoryNo":118,"categoryName":119,"taxonomyType":115,"taxonomyTypeDesc":116},[212,125,128,213,214,9,215,121,216,217,218,219,129,220,156,221,222,223,224,225],"root cause analysis","root","root cause","bitmovin observability root cause analysis","change","reflect","release","start","why","time","error","mix","metric","rate",{"skillNo":227,"name":228,"nameZh":6,"description":229,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":230,"categories":231,"keywords":240,"publishedAt":38},"01M6XCY63KD9ZQ5S5P4KSV881A","bitmovin-observability-collector-integration","Integrate the Bitmovin Observability (Analytics) collector into any video player on any platform. Use WHENEVER a developer wants to add Bitmovin Analytics \u002F Observability tracking, \"set up the collector\", \"enable analytics\", \"track playback \u002F QoE \u002F impressions\", wire up a player to the Bitmovin dashboard, or asks why their analytics data is missing, empty, or wrong after integrating. Covers Web, Android\u002FFire TV, iOS\u002FtvOS\u002FvisionOS, and Roku, for both the Bitmovin Player and third-party engines (HLS.js, Shaka, Video.js, HTML5, ExoPlayer, Media3, AVPlayer, THEOplayer, CAFv3). Use it even when the user only names their player (\"add analytics to my Shaka player\") without saying \"Bitmovin collector\". Knows that the Bitmovin Player has analytics pre-integrated while third-party players need a separate collector with a managed attach\u002Fdetach lifecycle.","https:\u002F\u002Fgithub.com\u002Fbitmovin\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fbitmovin-observability-collector-integration\u002FSKILL.md",[232,235],{"categoryNo":233,"categoryName":234,"taxonomyType":115,"taxonomyTypeDesc":116},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":236,"categoryName":237,"taxonomyType":238,"taxonomyTypeDesc":239},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",[125,241,242,9,243,244,245,151,129,220,246,155,247,156,248,135,249,250,251,136],"integration","collector","bitmovin observability collector integration","dashboard","data","video player","only","attach","my","track","managed"]