動画を Stream にアップロードすると、HLS / DASH でストリーミングできます。一方、ユースケースによっては MP4 または M4A ファイルをダウンロードしたいことがあります。 オフライン視聴などでは MP4 ファイルのダウンロードが向きます。AI による要約など下流の処理で音声だけ欲しい場合は、M4A ファイルのダウンロードのほうが便利なことがあります。
動画ごとに MP4 対応を有効にする手順は次のとおりです。
/downloadsまたは/downloads/defaultエンドポイントへ POST リクエストを送り、MP4 対応を有効にします。- エンドポイントのレスポンスにある MP4 URL を保存します。この MP4 URL は、次の手順で MP4 の準備ができたときに使えるようになります。
statusフィールドがreadyになるまで/downloadsエンドポイントをポーリングし、MP4 の利用開始を確認します。これで手順 2 の MP4 URL を使えます。
視聴可能な状態になったアップロード済み動画に対して、/downloads または /downloads/default エンドポイントへ HTTP リクエストを送ると、ダウンロードを有効にできます。
動画が視聴可能になったときの通知は、Webhook を使う を参照してください。
curl -X POST \
-H "Authorization: Bearer <API_TOKEN>" \
https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/stream/<VIDEO_UID>/downloadsconst client = new Cloudflare({
apiEmail: process.env['CLOUDFLARE_EMAIL'],
apiKey: process.env['CLOUDFLARE_API_KEY'],
});
const download = await client.stream.downloads.create({
account_id: '<ACCOUNT_ID>',
identifier: '<VIDEO_UID>',
});レスポンスには、ダウンロードの種類、URL、処理ステータスが含まれます。
{
"result": {
"default": {
"status": "inprogress",
"url": "https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/default.mp4",
"percentComplete": 75.0
}
},
"success": true,
"errors": [],
"messages": []
}外部アプリケーションから REST API を使う場合の詳細は、TypeScript、Python、Go 向けの事前生成 SDK も含め、Stream の REST API および SDK リファレンス を参照してください。
export default {
async fetch(request, env) {
const videoHandle = env.STREAM.video("VIDEO_ID");
const downloads = await videoHandle.downloads.generate();
return Response.json(downloads);
},
};{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "$today",
"observability": {
"enabled": true
},
"stream": {
"binding": "STREAM"
}
}詳細は Workers Stream バインディング API リファレンス を参照してください。
動画ごとに M4A 対応を有効にするには、MP4 ダウンロードの生成とほぼ同じ手順で、代わりに /downloads/audio エンドポイントへ POST リクエストを送ります。
curl -X POST \
-H "Authorization: Bearer <API_TOKEN>" \
https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/stream/<VIDEO_UID>/downloads/audioconst client = new Cloudflare({
apiEmail: process.env['CLOUDFLARE_EMAIL'],
apiKey: process.env['CLOUDFLARE_API_KEY'],
});
const download = await client.stream.downloads.audio.create({
account_id: '<ACCOUNT_ID>',
identifier: '<VIDEO_UID>',
});レスポンスには、ダウンロードの種類、URL、処理ステータスが含まれます。
{
"result": {
"audio": {
"status": "inprogress",
"url": "https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/audio.m4a",
"percentComplete": 75.0
}
},
"success": true,
"errors": [],
"messages": []
}外部アプリケーションから REST API を使う場合の詳細は、TypeScript、Python、Go 向けの事前生成 SDK も含め、Stream の REST API および SDK リファレンス を参照してください。
export default {
async fetch(request, env) {
const videoHandle = env.STREAM.video("VIDEO_ID");
const downloads = await videoHandle.downloads.generate("audio");
return Response.json(downloads);
},
};{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "$today",
"observability": {
"enabled": true
},
"stream": {
"binding": "STREAM"
}
}詳細は Workers Stream バインディング API リファレンス を参照してください。
動画の利用可能なダウンロードをすべて見るには、downloads API へ GET HTTP リクエストを送ります。
curl -X GET \
-H "Authorization: Bearer <API_TOKEN>" \
https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/stream/<VIDEO_UID>/downloadsconst client = new Cloudflare({
apiEmail: process.env['CLOUDFLARE_EMAIL'],
apiKey: process.env['CLOUDFLARE_API_KEY'],
});
const downloads = await client.stream.downloads.get({
account_id: '<ACCOUNT_ID>',
identifier: '<VIDEO_UID>',
});{
"result": {
"audio": {
"status": "ready",
"url": "https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/audio.m4a",
"percentComplete": 100.0
}
"default": {
"status": "ready",
"url": "https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/default.mp4",
"percentComplete": 100.0
}
},
"success": true,
"errors": [],
"messages": []
}外部アプリケーションから REST API を使う場合の詳細は、TypeScript、Python、Go 向けの事前生成 SDK も含め、Stream の REST API および SDK リファレンス を参照してください。
export default {
async fetch(request, env) {
const videoHandle = env.STREAM.video("VIDEO_ID");
const downloads = await videoHandle.downloads.get();
return Response.json(downloads);
},
};{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "$today",
"observability": {
"enabled": true
},
"stream": {
"binding": "STREAM"
}
}詳細は Workers Stream バインディング API リファレンス を参照してください。
ダウンロード可能なファイルの名前は、URL の末尾に filename クエリ文字列パラメーターを付けると変更できます。
次の例では、URL に ?filename=MY_VIDEO.mp4 を付けると、ファイル名が MY_VIDEO.mp4 になります。
https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/default.mp4?filename=MY_VIDEO.mp4
filename は最大 120 文字で、abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ の文字だけ使えます。拡張子(.mp4)は自動で付きます。
生成した MP4 ダウンロードファイルは、downloads API のレスポンスにあるリンクから取得できます。
curl -L https://customer-<CODE>.cloudflarestream.com/<VIDEO_UID>/downloads/default.mp4 > download.mp4動画のダウンロードを削除できます。種類は default と audio です。省略時は default になります。
curl -X DELETE \
-H "Authorization: Bearer <API_TOKEN>" \
https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/stream/<VIDEO_UID>/downloads/defaultconst client = new Cloudflare({
apiEmail: process.env['CLOUDFLARE_EMAIL'],
apiKey: process.env['CLOUDFLARE_API_KEY'],
});
await client.stream.downloads.default.delete({
account_id: '<ACCOUNT_ID>',
identifier: '<VIDEO_UID>',
});外部アプリケーションから REST API を使う場合の詳細は、TypeScript、Python、Go 向けの事前生成 SDK も含め、Stream の REST API および SDK リファレンス を参照してください。
export default {
async fetch(request, env) {
const videoHandle = env.STREAM.video("VIDEO_ID");
await videoHandle.downloads.delete();
return new Response("Download deleted", { status: 200 });
},
};{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "$today",
"observability": {
"enabled": true
},
"stream": {
"binding": "STREAM"
}
}詳細は Workers Stream バインディング API リファレンス を参照してください。
動画が公開なら、MP4 も公開アクセスできます。動画が非公開で視聴に署名付き URL が必要な場合、MP4 は公開されません。非公開動画の MP4 にアクセスするには、通常の視聴用と同じように署名付き URL を生成し、追加フラグ downloadable を true にします。
Stream バインディングで署名付きトークンを生成できます。
export default {
async fetch(request, env) {
const token = await env.STREAM.video("VIDEO_ID").generateToken();
return Response.json({ token });
},
};すでに署名付き URL が必要な動画では、トークンに downloadable フラグがないとダウンロードリンクは機能しません。
動画での署名付き URL の詳細は、Stream を保護する を参照してください。
トークンペイロードの例
{
"sub": <VIDEO_UID>,
"kid": <KEY_ID>,
"exp": 1537460365,
"nbf": 1537453165,
"downloadable": true,
"accessRules": [
{
"type": "ip.geoip.country",
"action": "allow",
"country": [
"GB"
]
},
{
"type": "any",
"action": "block"
}
]
}MP4 のダウンロードは、動画のストリーミングと同じ方法で課金されます。MP4 がダウンロードされるたびに、その動画の再生時間分が課金されます。たとえば、10 分の動画が月に 100 回ダウンロードされた場合、配信時間は 1,000 分として計上されます。
MP4 を有効にしても、追加のストレージ料金はかかりません。