> ## Documentation Index
> Fetch the complete documentation index at: https://gcore-doc-2189.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# HEVC, AV1, and VP9 multi-codec VOD

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).map(c => {
    if (!c || !c.props) return null;
    if (c.props.id) return c;
    const inner = c.props.children;
    if (inner && inner.props && inner.props.id) return inner;
    return null;
  }).filter(Boolean);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
    window.dispatchEvent(new Event("scroll"));
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    ## Multi-codec for lower CDN costs

    <p>Many VOD libraries are still stored and delivered mainly in H.264. H.264 is widely compatible, but it usually needs more bitrate than newer codecs to reach the same visual quality. For large catalogs, this directly affects CDN traffic costs.</p>

    <p>With multi-codec VOD, Gcore can create additional **HEVC**,  **AV1**, and **VP9** renditions from your uploaded source videos. Players can then choose the most efficient codec supported by each device. Viewers keep the same visual quality, while compatible devices receive smaller video segments and generate less CDN traffic.</p>

    <p>Live streaming with advanced codecs can be designed for live broadcasting too, but it requires additional validation of the ingest, transcoding, packaging, latency, and player path before launch.</p>

    <p>This feature is designed for enterprise customers with large VOD libraries and high delivery volume. It is available with premium transcoding. To activate it, contact your salesperson or account manager.</p>

    <Info>
      Premium transcoding is a paid feature.
    </Info>

    ## Demo video

    <iframe title="Multi-codec VOD demo player" src="https://player.gvideo.co/videos/2675_5aT2bPTFEN2BSQFm" width="100%" height="420" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen />

    <p>The demo video has AV1, VP9, HEVC, and H.264 renditions. Note that while Firefox handles VP9 playback successfully, Chrome has issues of playing VP9.</p>

    <table className="w-full text-left border-collapse">
      <thead>
        <tr>
          <th className="p-2 border-b">Codec</th>
          <th className="p-2 border-b">Manifest codec ID</th>
          <th className="p-2 border-b">Resolution</th>
          <th className="p-2 border-b">Video bitrate</th>
          <th className="p-2 border-b">Reduction vs H.264</th>
        </tr>
      </thead>

      <tbody>
        <tr style={{backgroundColor: 'rgba(147, 51, 234, 0.08)'}}>
          <td className="p-2">AV1</td>
          <td className="p-2">`av01.0.16M.08`</td>
          <td className="p-2">4839x2160</td>
          <td className="p-2">12 Mbps</td>
          <td className="p-2">About 50% vs 24 Mbps H.264 4K</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(147, 51, 234, 0.08)'}}>
          <td className="p-2">AV1</td>
          <td className="p-2">`av01.0.12M.08`</td>
          <td className="p-2">2420x1080</td>
          <td className="p-2">3 Mbps</td>
          <td className="p-2">50%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(147, 51, 234, 0.08)'}}>
          <td className="p-2">AV1</td>
          <td className="p-2">`av01.0.08M.08`</td>
          <td className="p-2">1613x720</td>
          <td className="p-2">1.35 Mbps</td>
          <td className="p-2">50%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(147, 51, 234, 0.08)'}}>
          <td className="p-2">AV1</td>
          <td className="p-2">`av01.0.04M.08`</td>
          <td className="p-2">1049x468</td>
          <td className="p-2">400 Kbps</td>
          <td className="p-2">50%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(147, 51, 234, 0.08)'}}>
          <td className="p-2">AV1</td>
          <td className="p-2">`av01.0.04M.08`</td>
          <td className="p-2">807x360</td>
          <td className="p-2">225 Kbps</td>
          <td className="p-2">50%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(2, 132, 199, 0.08)'}}>
          <td className="p-2">VP9</td>
          <td className="p-2">`vp09.00.10.08`</td>
          <td className="p-2">4840x2160</td>
          <td className="p-2">12 Mbps</td>
          <td className="p-2">About 50% vs 24 Mbps H.264 4K</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(2, 132, 199, 0.08)'}}>
          <td className="p-2">VP9</td>
          <td className="p-2">`vp09.00.10.08`</td>
          <td className="p-2">2420x1080</td>
          <td className="p-2">3.5 Mbps</td>
          <td className="p-2">42%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(2, 132, 199, 0.08)'}}>
          <td className="p-2">VP9</td>
          <td className="p-2">`vp09.00.10.08`</td>
          <td className="p-2">1612x720</td>
          <td className="p-2">1.5 Mbps</td>
          <td className="p-2">44%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(2, 132, 199, 0.08)'}}>
          <td className="p-2">VP9</td>
          <td className="p-2">`vp09.00.10.08`</td>
          <td className="p-2">1048x468</td>
          <td className="p-2">450 Kbps</td>
          <td className="p-2">44%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(2, 132, 199, 0.08)'}}>
          <td className="p-2">VP9</td>
          <td className="p-2">`vp09.00.10.08`</td>
          <td className="p-2">806x360</td>
          <td className="p-2">250 Kbps</td>
          <td className="p-2">44%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(22, 163, 74, 0.08)'}}>
          <td className="p-2">HEVC</td>
          <td className="p-2">`hev1.1.2.L180.90`</td>
          <td className="p-2">4839x2160</td>
          <td className="p-2">14.4 Mbps</td>
          <td className="p-2">About 40% vs 24 Mbps H.264 4K</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(22, 163, 74, 0.08)'}}>
          <td className="p-2">HEVC</td>
          <td className="p-2">`hev1.1.2.L150.90`</td>
          <td className="p-2">2420x1080</td>
          <td className="p-2">3.6 Mbps</td>
          <td className="p-2">40%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(22, 163, 74, 0.08)'}}>
          <td className="p-2">HEVC</td>
          <td className="p-2">`hev1.1.2.L120.90`</td>
          <td className="p-2">1613x720</td>
          <td className="p-2">1.62 Mbps</td>
          <td className="p-2">40%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(22, 163, 74, 0.08)'}}>
          <td className="p-2">HEVC</td>
          <td className="p-2">`hev1.1.2.L90.90`</td>
          <td className="p-2">1049x468</td>
          <td className="p-2">480 Kbps</td>
          <td className="p-2">40%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(22, 163, 74, 0.08)'}}>
          <td className="p-2">HEVC</td>
          <td className="p-2">`hev1.1.2.L90.90`</td>
          <td className="p-2">807x360</td>
          <td className="p-2">270 Kbps</td>
          <td className="p-2">40%</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(107, 114, 128, 0.08)'}}>
          <td className="p-2">H.264</td>
          <td className="p-2">`avc1.4d0033`</td>
          <td className="p-2">4096x1828</td>
          <td className="p-2">24 Mbps</td>
          <td className="p-2">Baseline</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(107, 114, 128, 0.08)'}}>
          <td className="p-2">H.264</td>
          <td className="p-2">`avc1.4d0032`</td>
          <td className="p-2">2420x1080</td>
          <td className="p-2">6 Mbps</td>
          <td className="p-2">Baseline</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(107, 114, 128, 0.08)'}}>
          <td className="p-2">H.264</td>
          <td className="p-2">`avc1.4d0020`</td>
          <td className="p-2">1613x720</td>
          <td className="p-2">2.7 Mbps</td>
          <td className="p-2">Baseline</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(107, 114, 128, 0.08)'}}>
          <td className="p-2">H.264</td>
          <td className="p-2">`avc1.4d001f`</td>
          <td className="p-2">1049x468</td>
          <td className="p-2">800 Kbps</td>
          <td className="p-2">Baseline</td>
        </tr>

        <tr style={{backgroundColor: 'rgba(107, 114, 128, 0.08)'}}>
          <td className="p-2">H.264</td>
          <td className="p-2">`avc1.4d001e`</td>
          <td className="p-2">807x360</td>
          <td className="p-2">450 Kbps</td>
          <td className="p-2">Baseline</td>
        </tr>

        <tr>
          <td className="p-2">AAC audio</td>
          <td className="p-2">`mp4a.40.2`</td>
          <td className="p-2">Audio only</td>
          <td className="p-2">64, 128, and 192 Kbps</td>
          <td className="p-2">—</td>
        </tr>

        <tr>
          <td className="p-2">Subtitles</td>
          <td className="p-2">WebVTT</td>
          <td className="p-2">English</td>
          <td className="p-2">—</td>
          <td className="p-2">—</td>
        </tr>
      </tbody>
    </table>

    <Note>
      Gcore uses generic encoding parameters that fit many video libraries out of the box. If you have your own quality targets, bitrate ladder, codec priorities, or device requirements, Gcore can review them and apply custom transcoding settings for your workflow.
    </Note>

    <Info>
      Gcore uses modern NVIDIA and Intel GPU encoding and decoding hardware in multiple regions worldwide. This helps process large transcoding workloads quickly and makes multi-codec preparation practical for large VOD libraries, especially using batch-migration).
    </Info>

    ## HLS manifest example

    <p>The demo HLS master manifest is available at:</p>

    ```text theme={null}
    https://demo-public.gvideo.io/videos/2675_5aT2bPTFEN2BSQFm/master.m3u8
    ```

    <p>It contains AV1, HEVC, and H.264 video variants with AAC audio:</p>

    ```m3u8 theme={null}
    #EXTM3U

    #EXT-X-STREAM-INF:BANDWIDTH=12192000,RESOLUTION=4839x2160,FRAME-RATE=24.000,CODECS="av01.0.16M.08,mp4a.40.2",SUBTITLES="subs0"
    index-s0q5739v1-v1-a1.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=14592000,RESOLUTION=4839x2160,FRAME-RATE=24.000,CODECS="hev1.1.2.L180.90,mp4a.40.2",SUBTITLES="subs0"
    index-s0q5749v1-v1-a1.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=24192000,RESOLUTION=4096x1828,FRAME-RATE=24.000,CODECS="avc1.4d0033,mp4a.40.2",SUBTITLES="subs0"
    index-s0q5759v1-v1-a1.m3u8
    ...
    ```

    <p>When a video has any non-H.264 codec, `master.m3u8` automatically uses HLS CMAF with fragmented MP4 (`.m4s`) chunks for the modern-codec variants. The player still opens the same `master.m3u8` URL, but the variant playlists contain `.m4s` chunks instead of only `.ts` segments.</p>

    ```m3u8 theme={null}
    #EXT-X-MAP:URI="init-s0q5737v1-v1-a1.m4s"
    #EXTINF:2.000,
    segment-1-s0q5737v1-v1-a1.m4s
    #EXTINF:2.000,
    segment-2-s0q5737v1-v1-a1.m4s
    ```

    <p>For the detailed technical explanation, see [HLS TS and CMAF formats](/streaming/video-hosting/hls-and-mp4#hls-ts-and-cmaf-formats).</p>

    ## MPEG-DASH manifest example

    <p>The demo MPEG-DASH manifest is available at:</p>

    ```text theme={null}
    https://demo-public.gvideo.io/videos/2675_5aT2bPTFEN2BSQFm/master.mpd
    ```

    <p>It groups codecs into separate `AdaptationSet` blocks. VP9 and AV1 are delivered as WebM chunks, while HEVC and H.264 are delivered as fragmented MP4 chunks:</p>

    ```xml theme={null}
    <AdaptationSet id="1" maxWidth="4840" maxHeight="2160" maxFrameRate="24">
      <SegmentTemplate
          media="dash-segment-$Number$-$RepresentationID$.webm"
          initialization="dash-init-$RepresentationID$.webm" />
      <Representation
          id="f1-v1-x3"
          mimeType="video/webm"
          codecs="vp09.00.10.08"
          width="4840"
          height="2160"
          bandwidth="12000000" />
    </AdaptationSet>

    <AdaptationSet id="2" maxWidth="4839" maxHeight="2160" maxFrameRate="24">
      <SegmentTemplate
          media="dash-segment-$Number$-$RepresentationID$.m4s"
          initialization="dash-init-$RepresentationID$.m4s" />
      <Representation
          id="f2-v1-x3"
          mimeType="video/mp4"
          codecs="hev1.1.2.L180.90"
          width="4839"
          height="2160"
          bandwidth="14400000" />
    </AdaptationSet>

    <AdaptationSet id="3" maxWidth="4839" maxHeight="2160" maxFrameRate="24">
      <SegmentTemplate
          media="dash-segment-$Number$-$RepresentationID$.webm"
          initialization="dash-init-$RepresentationID$.webm" />
      <Representation
          id="f3-v1-x3"
          mimeType="video/webm"
          codecs="av01.0.16M.08"
          width="4839"
          height="2160"
          bandwidth="12000000" />
    </AdaptationSet>

    <AdaptationSet id="4" maxWidth="4839" maxHeight="2160" maxFrameRate="24">
      <SegmentTemplate
          media="dash-segment-$Number$-$RepresentationID$.m4s"
          initialization="dash-init-$RepresentationID$.m4s" />
      <Representation
          id="f4-v1-x3"
          mimeType="video/mp4"
          codecs="avc1.4d0033"
          width="4096"
          height="1828"
          bandwidth="24000000" />
    </AdaptationSet>
    ...
    ```

    ## Activation

    <p>HEVC, AV1, and VP9 multi-codec transcoding is available for enterprise customers who use premium transcoding. To activate it, contact your salesperson or account manager and share:</p>

    * Expected library size and monthly traffic
    * Current source codec, usually H.264
    * Target devices and geographies
    * Required codecs: HEVC, AV1, VP9, or a subset
    * Expected migration plan for existing assets

    <p>After activation, Gcore will configure the required transcoding presets for your account.</p>

    ## Related pages

    <CardGroup cols={2}>
      <Card title="Output codecs and parameters" icon="settings" href="/streaming/live-streams-and-videos-protocols-and-codecs/output-parameters-and-codecs">
        Review default and custom transcoding outputs
      </Card>

      <Card title="HLS, MPEG-DASH, MP4" icon="play" href="/streaming/video-hosting/hls-and-mp4">
        Learn how modern codecs are delivered to players
      </Card>
    </CardGroup>
  </MethodSection>

  <MethodSection id="api" label="REST API">
    <p>After multi-codec quality presets are configured for the account, the Streaming API exposes the preset IDs and codec-specific manifest URL modifiers. Use <code>quality\_set\_id</code> when uploading videos to request multi-codec transcoding, then serve codec-filtered manifests to players based on device capability.</p>

    <Info>
      An [API token](/account-settings/api-tokens) is required.
    </Info>

    <p>Open a terminal and export the required variables:</p>

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export VIDEO_ID="{YOUR_VIDEO_ID}"
    ```

    ## List multi-codec quality presets

    <p>Returns all custom quality presets configured for the account, including multi-codec VOD presets. Use the <code>id</code> field when uploading a video to request multi-codec transcoding.</p>

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        from gcore import Gcore

        client = Gcore()
        quality_sets = client.streaming.quality_sets.list()

        for preset in quality_sets.vod:
            print(f"ID: {preset.id}  Name: {preset.name}  Default: {preset.default}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"

            gcore "github.com/G-Core/gcore-go"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            qualitySets, err := client.Streaming.QualitySets.List(ctx)
            if err != nil {
                panic(err)
            }

            for _, preset := range qualitySets.Vod {
                fmt.Printf("ID: %d  Name: %s  Default: %v\n", preset.ID, preset.Name, preset.Default)
            }
        }
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        curl "https://api.gcore.com/streaming/quality_sets" \
             -H "Authorization: APIKey $GCORE_API_KEY"
        ```

        <p>The API returns:</p>

        ```json theme={null}
        {
          "vod": [
            {
              "id": 42,
              "name": "Multi-codec AV1+HEVC+H.264",
              "default": true,
              "qualities": [
                {"id": 11, "name": "vod2160n"},
                {"id": 12, "name": "vod1080n"},
                {"id": 13, "name": "vod720n"}
              ]
            }
          ],
          "live": []
        }
        ```
      </Tab>
    </Tabs>

    <Note>
      To upload a video with a multi-codec preset, pass the `quality_set_id` value to `POST /streaming/videos`. See [Upload a video](/streaming/video-hosting/upload-a-video-and-embed-it-to-your-app) for the full request format.
    </Note>

    ## Access codec-specific HLS manifests

    <p>Every video object returned by <code>GET /streaming/videos/{id}</code> includes an <code>hls\_url</code> field. Append a codec suffix to serve a manifest containing only one codec family — useful when targeting specific device types or running A/B tests.</p>

    | Suffix             | Returns                         |
    | ------------------ | ------------------------------- |
    | `master.m3u8`      | All transcoded codecs (default) |
    | `master-av1.m3u8`  | AV1 renditions only             |
    | `master-hevc.m3u8` | HEVC renditions only            |
    | `master-h264.m3u8` | H.264 renditions only           |
    | `master-cmaf.m3u8` | CMAF HLS with fMP4 chunks       |

    <Tabs>
      <Tab title="curl">
        ```bash theme={null}
        # Replace VOD_CDN_HOST, CLIENT_ID, and SLUG with values from video.hls_url

        # Full manifest — all codecs
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master.m3u8"

        # AV1-only manifest
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master-av1.m3u8"

        # HEVC-only manifest
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master-hevc.m3u8"

        # H.264-only manifest (legacy device fallback)
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master-h264.m3u8"
        ```
      </Tab>
    </Tabs>

    ## Access codec-specific MPEG-DASH manifests

    <p>The <code>dash\_url</code> field from the video object also supports codec suffixes. AV1 renditions are delivered in WebM containers, while HEVC and H.264 use fragmented MP4.</p>

    | Suffix            | Returns              |
    | ----------------- | -------------------- |
    | `master.mpd`      | All codecs (default) |
    | `master-av1.mpd`  | AV1 in WebM          |
    | `master-hevc.mpd` | HEVC in fMP4         |
    | `master-h264.mpd` | H.264 in fMP4        |

    <Tabs>
      <Tab title="curl">
        ```bash theme={null}
        # AV1-only MPEG-DASH manifest
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master-av1.mpd"

        # HEVC-only MPEG-DASH manifest
        curl "https://VOD_CDN_HOST/videos/CLIENT_ID_SLUG/master-hevc.mpd"
        ```
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
