---
title: "Cloudflare Streamとは？動画アップロードから配信・視聴制限までのAPI実装と料金【2026年11月時点】"
url: "https://www.issoh.co.jp/tech/details/19159/"
published: 2026-11-01
updated: 2026-11-01
categories: ["インフラ・クラウド"]
publisher: "株式会社一創"
---

# Cloudflare Streamとは？動画アップロードから配信・視聴制限までのAPI実装と料金【2026年11月時点】

Cloudflare Streamは、動画のアップロード、保存、エンコード、配信をひとつのAPIで扱えるCloudflareの動画基盤です。[公式ドキュメント](https://developers.cloudflare.com/stream/)によると、ライブとオンデマンドの両方を、配信サーバーを構築・運用せずに自社のWebサイトやアプリへ組み込めます。料金は保存した分数と配信した分数の2軸だけで、エンコードと帯域には別料金がかかりません。

この記事では、curlでのアップロード、利用者のブラウザから直接送らせる方法、Webhookの署名検証、プレーヤーの埋め込み、署名付きURLによる視聴制限、ライブ配信、月額の試算、受託開発で採用するかどうかの線引きまでを、動くコード付きで扱います。ASPを使うか自社で作るかという全体の選び方は、[動画配信システムの仕組みとASP/自社開発の選び方を整理した記事](https://www.issoh.co.jp/column/details/15267/)で解説しています。

## まとめ：Cloudflare Streamで動画配信を組む条件と自前構築へ回す条件

結論から書きます。社内研修、会員向けの講座、製品紹介のように、1080pまでのH.264で足り、署名付きURLで視聴者を絞れば十分な動画なら、Cloudflare Streamで組むのが早くて安上がりです。逆に、映画やスポーツ中継のように権利者からDRMを求められる動画や、4K・HDRのまま届けたい動画は、Streamを主軸にしません。

- **任せられる範囲**：保存、H.264へのエンコード、360p〜1080pのアダプティブ配信、プレーヤー、サムネイル
- **自社で書く範囲**：アップロード後の公開フラグ管理、視聴権限の判定、トークン発行、Webhookの受け口
- **料金**：保存は1,000分あたり月5ドルの前払い、配信は1,000分あたり1ドルの後払い
- **見送る条件**：Widevine・FairPlayのDRMが契約条件にある、4K・HDRで配信したい

## Cloudflare Streamの仕組みとエンコード・配信を1つのAPIで担う範囲

Streamに動画を1本送ると、UIDという識別子が振られます。以降の再生URL、権限設定、削除はすべてこのUIDで行います。サーバー、ストレージのバケット、トランスコードのジョブ、CDNの設定を別々に用意する必要はありません。

### H.264・360p〜1080pの出力とHDRがSDRになるエンコード仕様

公式ドキュメントでは、出力はH.264のアダプティブビットレートで、解像度は360pから1080pまでと説明されています。[FAQ](https://developers.cloudflare.com/stream/faq/)には、HDRの動画はSDRに再エンコードして配信すると書かれています。入稿の推奨はMP4コンテナ、H.264映像、AAC音声です。

実務で効くのは、出力仕様を選べない点です。4Kの素材を入れても視聴者に届くのは1080pまでで、HDRの色域も残りません。デザイン会社の作品紹介や映像制作会社のポートフォリオのように画質そのものが商品になる案件では、この仕様が採否を決めます。

### 自前のHLS配信基盤と比べてStreamが引き受ける動画変換・配信の工程

自社でHLS配信を組む場合と比べると、Streamが引き受ける工程は次のとおりです。

| 工程    | 自前で組む場合             | Cloudflare Stream       |
| ----- | ------------------- | ----------------------- |
| 動画の保存 | オブジェクトストレージを用意      | Stream側に保存（最大30GB/本）    |
| エンコード | FFmpeg等でHLS・DASHを生成 | アップロード後に自動で生成           |
| 配信    | CDNとキャッシュ設定を構成      | Cloudflareのネットワークから配信   |
| プレーヤー | hls.js等を組み込む        | iframeのStream Playerを提供 |
| 視聴制限  | 署名付きCookie等を自作      | 署名付きURLとaccessRules     |
| DRM   | DRMライセンスサーバーと連携     | 公式ドキュメントに記載なし           |

表の上から5行は、Streamに任せると自社のコードから消えます。DRMの行だけは代わりが無いため、必要な案件では[トランスコードからHLS配信・DRMまでを自前で組む実装解説](https://www.issoh.co.jp/tech/details/15964/)の構成を検討してください。

## APIトークン作成からcurlで動画をアップロードしUIDを得る手順

前提は、Cloudflareのアカウントと、Streamの編集権限を付けたAPIトークンです。アカウントIDはダッシュボードで確認できます。アップロードの方法は、ファイルの大きさと送り手が誰かで3通りに分かれます。

### 200MB未満はフォーム送信・超える動画はtusで分割アップロード

[基本のアップロード手順](https://developers.cloudflare.com/stream/uploading-videos/upload-video-file/)では、200MB未満のファイルを`file`という名前のフォーム項目で送ります。

```
# 事前に環境変数へ入れておく（Stream編集権限のAPIトークン）
export ACCOUNT_ID="your-account-id"
export API_TOKEN="your-api-token"

# 200MB未満の動画をフォーム送信でアップロードする
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  --form file=@./training-01.mp4 \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/stream"

# 応答の result.uid が動画のID。以降の再生・権限設定はこのUIDで行う
```

200MBを超える動画は、[tusによる再開可能なアップロード](https://developers.cloudflare.com/stream/uploading-videos/resumable-uploads/)が必須です。チャンクの大きさは最小5MiB、最大200MiBで、回線が安定していれば50MiBが推奨されています。チャンクは256KiBの倍数で揃える決まりがあり、途中で大きさを変えると失敗します。研修の録画のように1本が数GBになる動画を扱うなら、最初からtus対応のクライアントで実装したほうが手戻りがありません。

### 利用者のブラウザから直接送らせるDirect Creator Uploadsの発行

会員や講師に動画を投稿させる場合、ファイルを自社サーバー経由で中継すると帯域と処理時間を余計に使います。[Direct Creator Uploads](https://developers.cloudflare.com/stream/uploading-videos/direct-creator-uploads/)は、1回だけ使えるアップロードURLをサーバー側で発行し、ブラウザからStreamへ直接送らせる仕組みです。APIトークンをブラウザに渡さずに済みます。

```
# 利用者に渡す1回限りのアップロードURLをサーバー側で発行する
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  --data '{ "maxDurationSeconds": 3600 }' \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/stream/direct_upload"

# 応答の result.uploadURL をブラウザへ返し、result.uid を自社DBに控える
```

`maxDurationSeconds`は受け付ける動画の最大秒数です。アップロードが終わるまで、この秒数が保存枠から予約として差し引かれます。何も考えずに大きな値を入れると、投稿が集中した日に保存枠が埋まり、新規のアップロードが止まります。投稿ルールで決めた上限に合わせて小さく指定しましょう。

### Webhookでエンコード完了のreadyToStreamを受けて署名を検証する

アップロード直後の動画はエンコード中で、すぐには再生できません。完了を知るには[Webhook](https://developers.cloudflare.com/stream/manage-video-library/using-webhooks/)を使います。購読はアカウントに1件だけで、`localhost`やローカルIPには送られません。通知の本文には`readyToStream`と`status.state`が入り、失敗時は`error`になります。

通知が本物かどうかは、`Webhook-Signature`ヘッダで確かめます。ヘッダの時刻と本文を`.`でつないだ文字列に、購読時に返されるシークレットでHMAC-SHA256を計算し、`sig1`の値と比べる方式です。受け口をCloudflare Workersで書くと、次のようになります。Workers自体の料金と使い方は[Cloudflare Workersの対応言語・無料枠・料金をまとめた記事](https://www.issoh.co.jp/tech/details/6760/)で確認できます。

```
// Cloudflare Workers で Stream の Webhook を受ける例
// 購読時に返る secret を STREAM_WEBHOOK_SECRET として登録しておく
const enc = new TextEncoder();

function hexToBytes(hex) {
  const out = new Uint8Array(hex.length / 2);
  for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.substr(i * 2, 2), 16);
  return out;
}

export default {
  async fetch(request, env) {
    // ヘッダの形式は time=<UNIX秒>,sig1=<16進の署名>
    const header = request.headers.get("Webhook-Signature") || "";
    const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
    const body = await request.text(); // 改変せずに文字列のまま使う

    // 5分より古い通知は再送攻撃とみなして捨てる
    if (Math.abs(Date.now() / 1000 - Number(parts.time)) > 300) {
      return new Response("stale", { status: 400 });
    }

    const key = await crypto.subtle.importKey(
      "raw", enc.encode(env.STREAM_WEBHOOK_SECRET),
      { name: "HMAC", hash: "SHA-256" }, false, ["verify"]
    );
    // verify は定数時間で比較する
    const ok = await crypto.subtle.verify(
      "HMAC", key, hexToBytes(parts.sig1 || ""), enc.encode(`${parts.time}.${body}`)
    );
    if (!ok) return new Response("bad signature", { status: 401 });

    const video = JSON.parse(body);
    if (video.readyToStream) {
      // ここで自社DBの公開フラグを立てる（video.uid で突き合わせる）
    }
    return new Response("ok");
  },
};
```

本文を`JSON.parse`してから文字列に戻すと、空白や順序が変わって署名が合わなくなります。受け取った本文はそのまま使ってください。

## Stream Playerの埋め込みとHLSマニフェストを使う自前プレーヤー再生

再生の方法は、Cloudflareが用意するStream Playerを埋め込むか、HLS・DASHのマニフェストを自前のプレーヤーで読むかの2つです。デザインを細かく合わせる必要が無ければ、前者で十分です。

### iframe埋め込みのURL形式とmuted・preload・startTimeの指定例

[Stream Playerのページ](https://developers.cloudflare.com/stream/viewing-videos/using-the-stream-player/)では、アカウント固有の`customer-CODE.cloudflarestream.com`の下にUIDを置いたURLをiframeで読み込みます。`CODE`はダッシュボードで確認できる値です。

```
<iframe
  src="https://customer-CODE.cloudflarestream.com/VIDEO_UID/iframe?muted=true&preload=auto&startTime=1m30s"
  style="border: none"
  width="1280" height="720"
  allow="accelerometer; gyroscope; autoplay; encrypted-media; picture-in-picture;"
  allowfullscreen="true"
></iframe>
```

自動再生したいときは`autoplay`を付けますが、ブラウザは音声付きの自動再生を止めることがあるため、`muted`との併用が推奨されています。`autoplay=false`と書いても無効にはならず、パラメータ自体を外す必要がある点にも注意してください。

### hls.jsでvideo.m3u8を読み込む自前プレーヤーの設定例

[自前プレーヤーのページ](https://developers.cloudflare.com/stream/viewing-videos/using-own-player/)によると、HLSは`/manifest/video.m3u8`、DASHは`/manifest/video.mpd`で取得できます。SafariとiOSはHLSをそのまま再生でき、それ以外のブラウザでは[hls.js](https://github.com/video-dev/hls.js)を使います。

```
<video id="player" controls playsinline width="640"></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
  const src = "https://customer-CODE.cloudflarestream.com/VIDEO_UID/manifest/video.m3u8";
  const video = document.getElementById("player");
  if (video.canPlayType("application/vnd.apple.mpegurl")) {
    video.src = src; // Safari と iOS は HLS をそのまま再生できる
  } else if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(src);
    hls.attachMedia(video);
  }
</script>
```

マニフェストには複数の解像度が入っており、回線に応じた切り替えはプレーヤーが行います。`clientBandwidthHint`というクエリで特定のビットレートに寄せる方法もありますが、公式はプレーヤー側の設定で足りないときの最後の手段という位置付けです。

## 署名付きURLとaccessRulesで有料動画・社内動画の視聴を絞る設定

UIDを知っていれば誰でも見られる状態のままでは、有料講座や社内限定の動画には使えません。[視聴制限のページ](https://developers.cloudflare.com/stream/viewing-videos/securing-your-stream/)にある仕組みで、視聴者を絞ります。

### requireSignedURLsを有効にして有効期限1時間のトークンを発行

動画に`requireSignedURLs`を設定すると、UIDだけでは再生できなくなります。視聴の都度、自社のサーバーがログインや購入の状態を確かめてからトークンを発行し、そのトークンをUIDの位置に入れたURLを返す流れです。

```
# 1) 動画を署名付きURL必須に切り替える
curl --header "Authorization: Bearer $API_TOKEN" \
  --data '{ "uid": "VIDEO_UID", "requireSignedURLs": true }' \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/stream/VIDEO_UID"

# 2) 視聴の都度、サーバー側でトークンを発行する（既定の有効期限は1時間）
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/stream/VIDEO_UID/token"

# 3) 応答の result.token を UID の位置に入れて再生URLを組み立てる
# https://customer-CODE.cloudflarestream.com/TOKEN/manifest/video.m3u8
```

トークンの既定の有効期限は1時間で、独自に`exp`を指定する場合も署名時点から24時間以内に限られます。`allowedOrigins`で埋め込みを許すドメインを絞り、`accessRules`で国やIPによる許可・拒否を最大5件まで並べることもできます。

### 1日1,000件を超える発行は署名キーでの自前署名へ切り替える

`/token`のAPIは、検証用か、1日の発行が1,000件未満の場合に推奨されています。呼び出しごとにAPIのレート制限を消費するためです。会員数が増えて発行がこれを超えるなら、`/stream/keys`で署名キーを作り、自社のサーバーでトークンを署名する方式へ切り替えます。

署名キーは最大1,000個まで作れ、作成時に返る`pem`と`jwk`は二度と表示されません。作成直後にシークレット管理の仕組みへ保存し、漏れたらそのキーを削除して発行済みのトークンをまとめて無効にする手順まで、最初に決めておきましょう。

### DRMの記載はなく署名付きURLでは録画や再配布を防げない点

2026年11月時点で、視聴制限のページが扱うのは署名付きURL、`accessRules`、`allowedOrigins`で、Widevine・FairPlay・PlayReadyといったDRMの記載は見当たりませんでした。署名付きURLが防ぐのは、権限の無い人がURLを手に入れて再生することです。正規の視聴者が画面を録画する行為や、取得した映像の再配布までは止められません。

コンテンツの権利者からDRMを条件に出されている場合、Streamの機能だけでは契約を満たせないと判断してください。DRMライセンスの発行と視聴権限をどうつなぐかは、[視聴権限とDRMライセンス発行をつなぐ課金システムの実装設計](https://www.issoh.co.jp/tech/details/16501/)で扱っています。

## RTMPSでライブ配信を受けて自動録画をVODとして残す手順

[ライブ配信の手順](https://developers.cloudflare.com/stream/stream-live/start-stream-live/)では、ライブ入力を作ってOBSなどの配信ソフトに接続先を設定します。`recording.mode`を`automatic`にすると、配信がHLS・DASHで視聴できるようになり、終了後は録画がそのままオンデマンドの動画として残ります。

```
# ライブ入力を作成し、配信終了後は自動で録画をVODとして残す
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  --data '{"meta": {"name": "monthly-allhands"}, "recording": {"mode": "automatic"}}' \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/stream/live_inputs"

# OBS の設定
#   サーバー:         rtmps://live.cloudflare.com:443/live/
#   ストリームキー:   応答の result.rtmps.streamKey
```

配信ソフト側は、映像をH.264、音声をAACにします。キーフレーム間隔は通常のHLS・DASHで4〜8秒、低遅延のLL-HLSを使うなら2〜4秒が推奨値で、ビットレートは可能なら固定にします。LL-HLSはベータで、マニフェストのURLに`?protocol=llhls`を付けて使う方式です。全社集会や新製品発表をそのままアーカイブ化したい用途と相性がよく、配信と録画の保存を別々に組む手間がなくなります。

## 保存分数と配信分数の2軸課金で動画配信の月額費用を見積もる計算例

[料金のページ](https://developers.cloudflare.com/stream/pricing/)によると、課金は動画の長さで決まり、ファイルサイズには関係しません。オンデマンドとライブは同じ計算です。

| 項目                    | 単価            | 支払い方     |
| --------------------- | ------------- | -------- |
| 保存（Minutes stored）    | 1,000分あたり月5ドル | 前払いで枠を買う |
| 配信（Minutes delivered） | 1,000分あたり1ドル  | 使った分の後払い |
| 取り込み・エンコード            | 無料            | －        |
| 帯域                    | 配信料に含む        | －        |

保存枠を使い切ると、新しいアップロードとライブ配信の開始ができなくなります。WebRTCでの配信も2026年10月15日から課金対象になりました。

### 研修動画200本・月3万分視聴を想定した保存料と配信料の月額試算

社員500人の会社が、10分の研修動画を200本置き、1人あたり月60分見る場合を単価から計算します。保存は2,000分で、1,000分あたり5ドルなので月10ドルです。配信は500人×60分で30,000分になり、30ドルかかります。合計は月40ドル前後です。

この規模なら、配信サーバーとCDNを自前で持つより明らかに安く収まります。逆に配信分数が大きくなる動画、たとえば月に数百万分見られる一般公開の動画では、費用のうち配信料が支配的です。視聴時間から逆算した他社ASPとの比較は、[視聴時間から逆算するASP月額と自社構築の実額の記事](https://www.issoh.co.jp/column/details/15965/)の計算と並べると判断しやすくなります。

### 動画配信の4秒セグメント単位の計測と先読みも課金される注意点

配信分数は、プレーヤーが取りにいったHTTPリクエストから計測されます。アップロード動画の場合、計測の単位は4秒のセグメントです。視聴者が実際に見ていなくても、プレーヤーが先読みした分は課金されます。ブラウザのキャッシュから再生された分は対象外です。

試算より請求が膨らむ典型は、ページを開いただけで`preload=auto`により先頭部分が読み込まれる構成です。一覧ページに動画を何本も並べる場合は、`preload`を付けずにサムネイルを表示し、クリックしてから再生する作りにしたほうが無駄な配信分数を抑えられます。

## 受託開発でCloudflare Streamを採用する条件と自前構築へ回す場面

ここからは判断です。Streamは機能を足すほど便利になる製品ではなく、出力と保護の仕様が固定された製品です。その固定仕様を案件の要件が超えるかどうかで決めます。次の4条件がそろうなら、Streamで組んで構いません。

- **画質**：H.264の1080pで要件を満たし、4KやHDRを求められていない
- **保護**：守りたいのは「権限の無い人に見せない」ことで、署名付きURLで足りる
- **規模**：1本30GB以内に収まり、同時にエンコードする本数が既定の120本で足りる
- **権限管理**：会員や購入の判定を自社システム側で持ち、Streamには配信だけを任せられる

見送る場面ははっきりしています。権利者との契約でDRMが必須の動画配信サービスは、Streamを主軸にしません。4K・HDRで届けることが商品価値の映像サービスも同様です。この2つに当たる案件で「まずStreamで作って後から足す」と進めると、作り直しになります。

### LMS・会員サイトの権限管理と動画の保存・配信を組み合わせる構成の分担

採用する場合でも、Streamが担うのは動画の保存と配信までです。どの会員がどの講座を見られるか、視聴履歴を誰がどこまで見終えたか、未払いの会員を止める処理は、自社のシステムに残ります。実装の山場は、Webhookで受けた完了通知と講座の公開状態をつなぐ処理と、視聴の都度トークンを発行する処理の2か所です。

Streamを動画の部品として組み込み、会員管理や課金、LMSとの連携まで一体で設計したい場合は、[一創の動画配信システム開発](https://www.issoh.co.jp/service/system/vod/)で相談を受け付けています。Streamで足りるか、DRMを含めて自前で組むべきかの切り分けから一緒に進められます。

## よくある質問

Cloudflare Streamを検討するときによく出る疑問を、2026年11月時点の公式ドキュメントに沿って整理しました。

### Cloudflare Streamの料金にエンコードや帯域の費用は含まれますか？

含まれます。料金のページでは、取り込みとエンコードは無料で、帯域は配信分数の料金に含まれると書かれています。請求されるのは、保存した動画の分数（1,000分あたり月5ドルの前払い）と、配信した分数（1,000分あたり1ドルの後払い）の2つだけです。ファイルサイズは計算に関係しないため、高ビットレートの素材を入れても保存料は変わりません。大量に使う場合の割引は営業窓口への問い合わせになります。

### アップロードできる動画のサイズや本数に上限はありますか？

FAQによると、1本の上限は既定で30GBです。200MBを超える動画はtusでのアップロードが必須になります。本数そのものの上限ではなく、買った保存枠の分数を超える動画はアップロードできないという制約です。また、キュー待ちとエンコード中を合わせて同時に処理できるのは既定で120本までです。一度に数百本を移行する場合は、投入のペースを制御する仕組みを用意してください。

### 4KやHDRの動画はそのまま配信されますか？

されません。公式ドキュメントでは、出力はH.264のアダプティブビットレートで360pから1080pまでと説明されており、FAQにはHDRの動画をSDRへ再エンコードして配信すると書かれています。高画質の素材を入れても視聴者に届くのは1080pのSDRです。4KやHDRで見せることが要件の案件では、別の配信基盤を選ぶ必要があります。

### 視聴者がいないライブ配信にも料金はかかりますか？

配信料はかかりません。料金のページでは、視聴者のいないライブ配信の配信分数は0ドルと説明されています。ただし、録画を有効にしている場合、録画された分数は保存枠に加算されます。リハーサルの配信を録画したまま放置すると保存枠を圧迫するため、不要な録画は削除する運用を決めておくと安心です。

### Cloudflare R2に動画を置いて配信する方法とは何が違いますか？

R2はファイルを保存するオブジェクトストレージで、エンコードや解像度の切り替え、プレーヤー、視聴制限は自分で用意します。MP4を1本置いてそのまま再生させるだけならR2でも成り立ちますが、回線に応じて画質を切り替えるHLS配信にするには、FFmpeg等で変換するパイプラインの自前構築が必要です。Streamはその変換から配信までを含むため、動画の本数が多く、更新が頻繁な用途ほど差が出ます。

## 関連記事

- [動画配信システムの比較｜同時視聴数・DRM・課金・LMS連携で選ぶ判断軸](https://www.issoh.co.jp/column/details/15963/)：Stream以外の配信サービスと並べて比べる観点を確認できます
- [動画配信システムのオープンソース8製品｜ライセンス条件と自前運用の限界を実装目線で判定](https://www.issoh.co.jp/tech/details/16500/)：自前で配信基盤を持つ場合の選択肢を押さえられます
- [VercelとCloudflare Pagesの違い：Next.jsの動かし方・料金の増え方・商用条件で選ぶ](https://www.issoh.co.jp/tech/details/18587/)：動画を埋め込むWebサイト側の置き場所を選ぶ材料になります
- [Cloudflare Containersとは？AIエージェントのサンドボックスを動かす手順と料金](https://www.issoh.co.jp/tech/details/18880/)：Cloudflare上でFFmpegなどの処理を動かす選択肢を確認できます
- [Cloudflare Python Workersとは？FastAPIをエッジで動かす手順とパッケージ制約](https://www.issoh.co.jp/tech/details/18259/)：Webhookやトークン発行の処理をPythonで書く場合の制約を確認できます

---

出典: [Cloudflare Streamとは？動画アップロードから配信・視聴制限までのAPI実装と料金【2026年11月時点】](<https://www.issoh.co.jp/tech/details/19159/>)（株式会社一創）
