Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stream/premium-encoding.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ In most cases, videos become playable within **10–15 seconds**, regardless of
JIT automatically adapts to different resolutions, bitrates, devices, and network conditions. This ensures a smooth playback experience across a wide range of environments, helping improve viewer engagement and retention. When content is instantly accessible and optimized for each viewer, users are more likely to stay, interact, and return.

<Info>
Just-in-Time (JIT) encoding is only supported by the Bunny player. We cannot guarantee it will work with 3rd party or custom video players.
Just-in-Time (JIT) encoding is only supported by the Bunny player. We cannot guarantee it will work with 3rd party or custom video players.
</Info>

#### Performance Considerations
Expand Down
55 changes: 37 additions & 18 deletions stream/tus-resumable-uploads.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ description: "Upload videos to Bunny Stream using the TUS protocol for resumable

The TUS resumable upload endpoint allows resumable and presigned uploads of video files. This enables end-users to upload directly to Bunny Stream and greatly improves reliability on poor networks and mobile connections.

The endpoint uses the open [tus protocol](https://tus.io/) for resumable file uploads. Before a video can be uploaded through the TUS endpoint, a video object must be created through the [Create Video](/api-reference/stream) API call to obtain the video ID.
The endpoint uses the open [TUS Protocol](https://tus.io/) for resumable file uploads. Before a video can be uploaded through the TUS endpoint, a video object must be created through the [Create Video API](/api-reference/stream) call to obtain the video ID.

## TUS endpoint
## TUS upload API endpoint

```text
https://video.bunnycdn.com/tusupload
```

## How it works

1. **Create a video object** using the [Create Video](/api-reference/stream) API to get a `videoId`.
1. **Create a video object** using the [Create Video API](/api-reference/stream) to get a `videoId`.
2. **Generate a presigned signature** on your server using SHA256.
3. **Upload the file** from the client using a TUS client library with the presigned credentials.

Expand All @@ -25,23 +25,23 @@ This approach allows secure direct uploads from end-users without exposing your

To authenticate a TUS upload request, the following headers must be included:

| Header | Description |
| ------------------------ | --------------------------------------------------- |
| `AuthorizationSignature` | SHA256 signature for request validation |
| `AuthorizationExpire` | UNIX timestamp (in seconds) when the upload expires |
| `LibraryId` | The ID of the video library |
| `VideoId` | The GUID of the previously created video object |
| Header | Description |
| --- | --- |
| `AuthorizationSignature` | SHA256 signature for request validation |
| `AuthorizationExpire` | UNIX timestamp (in seconds) when the upload expires |
| `LibraryId` | The ID of the video library |
| `VideoId` | The GUID of the previously created video object |

## Video metadata parameters

The following metadata can be passed with the TUS upload:

| Parameter | Required | Description |
| --------------- | -------- | -------------------------------------------------------- |
| `filetype` | Yes | The MIME type of the uploaded video (e.g., `video/mp4`) |
| `title` | Yes | The title of the video |
| `collection` | No | The GUID of the collection to upload to |
| `thumbnailTime` | No | Time in milliseconds to extract the main video thumbnail |
| Parameter | Required | Description |
| --- | --- | --- |
| `filetype` | Yes | The MIME type of the uploaded video (e.g., `video/mp4`) |
| `title` | Yes | The title of the video |
| `collection` | No | The GUID of the collection to upload to |
| `thumbnailTime` | No | Time in milliseconds to extract the main video thumbnail |

## Generating the signature

Expand Down Expand Up @@ -76,7 +76,6 @@ const signature = crypto
.digest("hex");
```


```php PHP
<?php

Expand All @@ -89,7 +88,6 @@ $signatureString = $libraryId . $apiKey . $expirationTime . $videoId;
$signature = hash("sha256", $signatureString);
```


```python Python
import hashlib
import time
Expand Down Expand Up @@ -241,7 +239,6 @@ export async function POST(request: NextRequest) {
}
```


```typescript components/VideoUploader.tsx
"use client";

Expand Down Expand Up @@ -445,3 +442,25 @@ const upload = new tus.Upload(file, {
<Info>
Ensure any `AuthorizationExpire` timestamp is at least 1 hour (3600 seconds) or longer to make sure uploads are completed before authorization expires.
</Info>

#### Resumable (TUS) upload FAQ

Common questions about how authorization and resumability behave when uploading video with the TUS resumable protocol.

<AccordionGroup>
<Accordion title="Is AuthorizationExpire validated on every request, or only when the upload is created?">
`AuthorizationExpire` is validated at the start of **every** `POST`, `HEAD`, and `PATCH` request - not only at upload creation. It is **not** rechecked during an active `PATCH`, so a chunk that is already streaming will not be interrupted mid-request if the signature expires while data is in flight.
</Accordion>

<Accordion title="Can I re-sign an existing video GUID to resume an in-progress upload instead of creating a new video object?">
Yes. The same video GUID can be re-signed and used to resume through the existing TUS upload URL - there is no need to create a new video object.

Note that a newly generated signature does **not** extend the upload resource's original expiry. Re-signing lets you continue an existing upload; it does not reset the clock on how long that upload remains available.
</Accordion>

<Accordion title="How long does an incomplete TUS upload stay resumable, and what's returned once it expires?">
An incomplete upload remains resumable until the `AuthorizationExpire` value that was used when it was created, or after roughly **48 hours of inactivity** - whichever comes first.

Once it expires, requesting the upload returns `404 Not Found `(not `410`).
</Accordion>
</AccordionGroup>