Настройка Video CDN и стриминга
Видео — самый тяжёлый тип контента. Прямая раздача с сервера убивает пропускную способность. Video CDN решает доставку, транскодирование в разные качества и адаптивный битрейт (ABR).
Cloudflare Stream
# Upload видео через API
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/stream" \
-H "Authorization: Bearer {token}" \
-F [email protected] \
-F meta='{"name":"Product Demo"}'
# Response:
# {
# "uid": "abc123",
# "thumbnail": "https://videodelivery.net/abc123/thumbnails/thumbnail.jpg",
# "playback": {
# "hls": "https://videodelivery.net/abc123/manifest/video.m3u8",
# "dash": "https://videodelivery.net/abc123/manifest/video.mpd"
# }
# }
// React компонент с Cloudflare Stream player
import { Stream } from '@cloudflare/stream-react';
export function VideoPlayer({ videoId }: { videoId: string }) {
return (
<Stream
src={videoId}
controls
responsive
preload="metadata"
poster={`https://videodelivery.net/${videoId}/thumbnails/thumbnail.jpg?time=5s&width=640`}
/>
);
}
Преимущества Cloudflare Stream:
- Автоматическое транскодирование в 360p/480p/720p/1080p/1440p
- HLS + DASH адаптивный битрейт
- Глобальный CDN без дополнительной настройки
- Защита от скачивания (signed URLs)
Mux: профессиональная платформа
// Node.js SDK
import Mux from '@mux/mux-node';
const mux = new Mux({
tokenId: process.env.MUX_TOKEN_ID!,
tokenSecret: process.env.MUX_TOKEN_SECRET!,
});
// Создание Asset из URL
const asset = await mux.video.assets.create({
input: [{ url: 'https://storage.mysite.com/raw/video.mp4' }],
playback_policy: ['public'],
encoding_tier: 'baseline', // или 'smart' для умного кодирования
mp4_support: 'standard', // для скачивания
});
console.log(asset.playback_ids?.[0]?.id);
// → playback_id для плеера
// Mux Player (встроенный плеер)
import MuxPlayer from '@mux/mux-player-react';
<MuxPlayer
playbackId={playbackId}
streamType="on-demand"
accentColor="#FF0000"
thumbnailTime={15}
metadata={{
video_title: 'Product Demo',
viewer_user_id: userId,
}}
/>
// Signed URLs для приватного контента
const token = await mux.jwt.signPlaybackId(playbackId, {
type: 'video',
expiration: '6h',
params: {
aud: 'v', // video
},
});
// URL с подписью
const signedUrl = `https://stream.mux.com/${playbackId}.m3u8?token=${token}`;
Собственный стриминг: HLS через FFmpeg + S3
# Транскодирование в HLS (несколько качеств)
ffmpeg -i input.mp4 \
-filter_complex "
[0:v]split=3[v1][v2][v3];
[v1]scale=1920:1080[1080p];
[v2]scale=1280:720[720p];
[v3]scale=854:480[480p]
" \
-map "[1080p]" -c:v libx264 -b:v 4000k -maxrate 4500k -bufsize 9000k \
-hls_time 6 -hls_playlist_type vod \
-hls_segment_filename "output/1080p_%03d.ts" output/1080p.m3u8 \
\
-map "[720p]" -c:v libx264 -b:v 2000k -maxrate 2500k -bufsize 5000k \
-hls_time 6 -hls_playlist_type vod \
-hls_segment_filename "output/720p_%03d.ts" output/720p.m3u8 \
\
-map "[480p]" -c:v libx264 -b:v 800k -maxrate 1000k -bufsize 2000k \
-hls_time 6 -hls_playlist_type vod \
-hls_segment_filename "output/480p_%03d.ts" output/480p.m3u8 \
\
-map 0:a -c:a aac -b:a 128k \
-hls_time 6 -hls_playlist_type vod \
-hls_segment_filename "output/audio_%03d.ts" output/audio.m3u8
# Создание мастер-плейлиста
cat > output/master.m3u8 << 'EOF'
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=4000000,RESOLUTION=1920x1080
1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720
720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=854x480
480p.m3u8
EOF
# Загрузка на S3 + Cloudflare CDN
aws s3 sync output/ s3://my-videos/videos/video-id/ \
--content-type "application/x-mpegURL" \
--exclude "*.ts" \
--cache-control "max-age=31536000,public"
aws s3 sync output/ s3://my-videos/videos/video-id/ \
--exclude "*.m3u8" \
--content-type "video/MP2T" \
--cache-control "max-age=31536000,public"
HLS.js плеер
'use client';
import { useEffect, useRef } from 'react';
import Hls from 'hls.js';
export function VideoPlayer({ src }: { src: string }) {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (!videoRef.current) return;
if (Hls.isSupported()) {
const hls = new Hls({ maxBufferLength: 30 });
hls.loadSource(src);
hls.attachMedia(videoRef.current);
return () => hls.destroy();
} else if (videoRef.current.canPlayType('application/vnd.apple.mpegurl')) {
// Safari поддерживает HLS нативно
videoRef.current.src = src;
}
}, [src]);
return (
<video
ref={videoRef}
controls
preload="metadata"
style={{ width: '100%' }}
/>
);
}
Настройка Cloudflare Stream или Mux с плеером — 1–2 рабочих дня. Собственный HLS-пайплайн с FFmpeg и S3 — 3–5 дней.







