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

# Instant clips

> Create instant clips from a live stream DVR buffer, list them, and save highlights as permanent VODs before they expire.

Clips cut a segment from an ongoing live stream using its DVR buffer. Use them to publish a highlight before the broadcast ends. Clips are temporary — they expire after up to 4 hours — but can also be saved as permanent VODs.

![Animation showing a live stream being cut into HLS and MP4 clips in real time](https://demo-files.gvideo.io/apidocs/clip_recording_mp4_hls.gif)

> [!NOTE]
>
> An [API token](/account-settings/api-tokens) is required. DVR must be enabled on the stream (`dvr_enabled: true`). Clips are cut from the DVR buffer — the stream must be live and actively receiving an ingest signal.

```bash theme={null}
export GCORE_API_KEY="{YOUR_API_KEY}"
export STREAM_ID="{YOUR_STREAM_ID}"
```

## Enable DVR

`dvr_duration` sets the DVR buffer size in seconds (30–14400). The clip duration cannot exceed this window. Enable DVR by updating the stream:

**curl**

```bash theme={null}
curl -X PATCH "https://api.gcore.com/streaming/streams/$STREAM_ID" \
     -H "Authorization: APIKey $GCORE_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"dvr_enabled": true, "dvr_duration": 3600}'
```

The API returns the updated stream object with `dvr_enabled: true` and `dvr_duration: 3600`.

## Create a clip

Cut a segment from an ongoing live stream. Specify `duration` in seconds and optionally `start` as a Unix timestamp. The clip becomes accessible at `start + duration` — requesting it before that returns `425 Too Early`. An expired clip returns `404`.

| Parameter | Required | Description |
| - | - | - |
| `duration` | Yes | Segment length in seconds. Maximum equals `dvr_duration`. Final length may vary slightly due to keyframe alignment. |
| `start` | No | Unix timestamp of the segment start. Defaults to the current time. |
| `expiration` | No | Unix timestamp when the clip expires. Range: 1 minute to 4 hours after clip end. Defaults to `start + duration + 3600`. |
| `vod_required` | No | `true` to also save as a permanent VOD in video hosting. |

**Python SDK**

```python theme={null}
import os
from gcore import Gcore

client = Gcore()
stream_id = int(os.environ["STREAM_ID"])

# Create a 60-second clip starting now
clip = client.streaming.streams.clips.create(
    stream_id,
    duration=60,
)
print(f"Clip ID: {clip.id}")
print(f"HLS: {clip.hls_master}")
print(f"MP4: {clip.mp4_master}")
print(f"Expires at: {clip.expiration}")
```

**Go SDK**

```go theme={null}
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

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

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

    streamID, _ := strconv.ParseInt(os.Getenv("STREAM_ID"), 10, 64)

    // Create a 60-second clip starting now
    clip, err := client.Streaming.Streams.Clips.New(ctx, streamID, streaming.StreamClipNewParams{
        Duration: 60,
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("Clip ID: %s\n", clip.ID)
    fmt.Printf("HLS: %s\n", clip.HlsMaster)
    fmt.Printf("MP4: %s\n", clip.MP4Master)
}
```

**curl**

```bash theme={null}
curl -X PUT "https://api.gcore.com/streaming/streams/$STREAM_ID/clip_recording" \
     -H "Authorization: APIKey $GCORE_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"duration": 60}'
```

The API returns the clip object:

```json theme={null}
{
  "id": "eycnb3utc6bk",
  "start": 1758113719,
  "duration": 60,
  "expiration": 1758117379,
  "vod_required": false,
  "video_id": null,
  "renditions": ["media_0_720", "media_1_468", "media_2_360"],
  "hls_master": "https://cid.domain.com/rec/111_1000/rec_eycnb3utc6bk_qsid42_master.m3u8",
  "mp4_master": "https://cid.domain.com/rec/111_1000/rec_eycnb3utc6bk_qsid42_master.mp4"
}
```

### Create a clip from an earlier segment

To cut a segment from the past, pass `start` as a Unix timestamp:

**Python SDK**

```python theme={null}
import os
import time
from gcore import Gcore

client = Gcore()
stream_id = int(os.environ["STREAM_ID"])

# Create a 30-second clip starting 2 minutes ago
start_time = int(time.time()) - 120  # 2 minutes ago

clip = client.streaming.streams.clips.create(
    stream_id,
    duration=30,
    start=start_time,
)
print(f"Clip ID: {clip.id}")
print(f"HLS: {clip.hls_master}")
```

**Go SDK**

```go theme={null}
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"
    "time"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/packages/param"
    "github.com/G-Core/gcore-go/streaming"
)

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

    streamID, _ := strconv.ParseInt(os.Getenv("STREAM_ID"), 10, 64)

    // Create a 30-second clip starting 2 minutes ago
    startTime := time.Now().Add(-2 * time.Minute).Unix()

    clip, err := client.Streaming.Streams.Clips.New(ctx, streamID, streaming.StreamClipNewParams{
        Duration: 30,
        Start:    param.NewOpt(startTime),
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("Clip ID: %s\n", clip.ID)
    fmt.Printf("HLS: %s\n", clip.HlsMaster)
}
```

**curl**

```bash theme={null}
START=$(date -d "2 minutes ago" +%s 2>/dev/null || date -v-2M +%s)

curl -X PUT "https://api.gcore.com/streaming/streams/$STREAM_ID/clip_recording" \
     -H "Authorization: APIKey $GCORE_API_KEY" \
     -H "Content-Type: application/json" \
     -d "{\"duration\": 30, \"start\": $START}"
```

To save the clip as a permanent VOD, set `vod_required: true`. When the clip is created, the response includes a `video_id`. Use `GET /streaming/videos/{video_id}` to retrieve the permanent HLS/MP4 URLs once transcoding completes.

## List clips

Retrieve all non-expired clips for a stream.

**Python SDK**

```python theme={null}
import os
from gcore import Gcore

client = Gcore()
stream_id = int(os.environ["STREAM_ID"])

clips = client.streaming.streams.clips.list(stream_id)
for clip in clips:
    print(f"Clip {clip.id}: duration={clip.duration}s, hls={clip.hls_master}")
```

**Go SDK**

```go theme={null}
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

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

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

    streamID, _ := strconv.ParseInt(os.Getenv("STREAM_ID"), 10, 64)

    clips, err := client.Streaming.Streams.Clips.List(ctx, streamID)
    if err != nil {
        panic(err)
    }
    for _, clip := range *clips {
        fmt.Printf("Clip %s: duration=%ds, hls=%s\n",
            clip.ID, clip.Duration, clip.HlsMaster)
    }
}
```

**curl**

```bash theme={null}
curl "https://api.gcore.com/streaming/streams/$STREAM_ID/clip_recording" \
     -H "Authorization: APIKey $GCORE_API_KEY"
```

The API returns an array of non-expired clip objects. Expired clips are automatically removed and no longer appear in the list.
