"YouTube'u tasarla", en sevilen sistem tasarımı sorularından biridir; çünkü ilginç kısımlar insanların beklediği yerde değildir. Web sunucuları sıradandır. Asıl iş, gigabaytları bir telefondan depolamaya güvenilir biçimde taşımak, tek bir yüklemeyi her cihazda ve her bağlantıda oynayan bir düzine sürüme dönüştürmek ve bu baytları kendi sunucularınızın neredeyse hiç görmediği bir CDN'den sunmaktır.
Bu yazı o hattı sırasıyla ele alıyor: yükleme, dönüştürme, paketleme, dağıtım. Uyarlayabileceğiniz bir mimari diyagram ve üzerine yazmaya değer kararlarla bitiyor.
Bir değil, iki sistem
Bir video platformu, bir veritabanını paylaşan iki sistemdir:
- Alım: içerik üreticileri yükler; platform dönüştürür ve paketler. Gecikme dakikalarla ölçülür ve kimse bunu dert etmez.
- Oynatma: izleyiciler oynat'a basar; ilk kare birkaç saniye içinde görünmeli ve takılmamalıdır.
Bunları iki şerit olarak çizin. Farklı sinyallere göre (saatlik yükleme ile eşzamanlı izleyici) ölçeklenirler ve farklı şekillerde arızalanırlar.
Yükleme: asla API sunucularınızdan geçmez
Video dosyaları büyüktür ve mobil bağlantılar kopar. Bundan iki kural çıkar:
- Doğrudan nesne depolamaya yükleyin. Yükleme API'si içerik üreticisinin kimliğini doğrular, bir video kaydı oluşturur ve önceden imzalı URL'ler döndürür. İstemci baytları doğrudan kovaya gönderir. API'niz asla gigabaytlara vekâlet etmez.
- Devam ettirilebilir yapın. Çok parçalı yükleme kullanın; böylece kopan bir bağlantı yalnızca başarısız parçayı yeniden dener. Örneğin Amazon S3 multipart upload parçaları bağımsız olarak yükler ve istemci yüklemeyi tamamladığında birleştirir.
Yükleme tamamlandığında depolama olayı (ya da istemcinin tamamlama çağrısı) kuyruğa bir dönüştürme işi koyar.
Dönüştürme: tek yükleme, uyarlanabilir bir bit hızı merdiveni
Oynatıcılar bant genişliğine göre kaliteyi değiştirir; bu yüzden her videoyu birkaç kez kodlarsınız: bir uyarlanabilir bit hızı (ABR) merdiveni. Tipik bir merdiven 240p ya da 360p civarından 1080p ya da 4K'ya kadar uzanır ve her basamağın kendi bit hızı vardır.
Dönüştürme yoğun CPU ister ve paralelleştirmesi çok kolaydır:
- Kaynağı anahtar karelerden bölerek birkaç saniyelik parçalara ayırın.
- Her parçayı ve her sürümü, genellikle FFmpeg ile, bir işçi filosunda bağımsız bir iş olarak kodlayın.
- Sonuçları birleştirin ya da segment olarak tutun.
İki saatlik bir film böylece saatler yerine dakikalar içinde dönüştürülür ve başarısız bir iş tek bir parçayı yeniden dener. İşleri video, sürüm ve parçaya göre anahtarlayarak idempotent yapın; böylece bir yeniden deneme kopya üretmek yerine üzerine yazar.
Tüm içerik için tek bir merdiven bit israf eder: durağan bir slayt sunumu bir futbol maçından çok daha az bit hızına ihtiyaç duyar. Netflix, merdiveni her video için karmaşıklığına göre seçen başlık başına kodlamayı (per-title encoding) yaygınlaştırdı. Sabit bir merdivenle başlayıp başlık başına kodlamaya sonra geçebilirsiniz.
Paketleme: HLS, DASH ve CMAF
Oynatıcılar tek bir büyük dosya indirmez. Sürümleri ve segmentleri listeleyen bir manifest okur, sonra her biri birkaç saniyelik segmentleri düz HTTP üzerinden çekerler.
| Format | Tanımlayan | Tipik oynatıcılar |
|---|---|---|
| HLS | RFC 8216 | Apple cihazları, hls.js gibi oynatıcılarla çoğu tarayıcı |
| MPEG-DASH | ISO/IEC 23009-1 | Android, akıllı TV'ler, dash.js ve Shaka Player ile tarayıcılar |
| CMAF | ISO/IEC 23000-19 | Hem HLS hem DASH manifestleri için tek bir parçalı MP4 segment seti |
Paketleyicinin önemli olmasının nedeni CMAF'tir: onunla her videonun iki kopyası yerine tek bir segment seti saklar ve iki manifest yazarsınız. Kısa segmentler daha hızlı başlar ve kaliteyi daha erken değiştirir; uzun segmentler daha az istek harcar. Apple'ın HLS yazım belirtimi segment süresi, anahtar kareler ve merdivenler için somut öneriler listeler.
Ücretli içerik DRM ekler. Paketleyici segmentleri ortak şifrelemeyle (CENC) bir kez şifreler ve her platformun DRM sistemi (Widevine, FairPlay, PlayReady) bir lisans sunucusu üzerinden oynatıcılara lisans verir.
Dağıtım: işi CDN yapar
Segmentler statik dosyalardır ve bütün mesele de budur: bir CDN onları izleyicilere yakın yerlerde önbelleğe alır ve popüler bir video neredeyse tamamen uç önbelleklerden sunulur. Köken, sürüm kovasıdır; genellikle bir origin shield'ın arkasındadır, böylece 50 uç konumdaki bir önbellek ıskalaması depolamaya tek bir istek olur.
Oynatma API'si küçük kalır: izleyicinin videoyu izleyip izleyemeyeceğini kontrol eder, bir manifest URL'si döndürür (içerik özelse imzalı) ve analitik için oynatma olaylarını kaydeder.
Canlı yayın farklı bir hattır
Canlı video paketlemeyi ve CDN'i yeniden kullanır ama alımı değiştirir. Bir kodlayıcı, RTMP ya da SRT gibi bir protokolle bir alım sunucusuna akış iter; sunucu merdiveni gerçek zamanlı dönüştürür ve birkaç saniyede bir yeni segmentler yazar. Gecikme, segment uzunluğu artı oynatıcının arabelleğinden gelir; HLS ve DASH'in düşük gecikmeli modları, birkaç saniyeye yaklaşmak için bir segmentin parçalarını o segment tamamlanmadan iletir. Canlı ve isteğe bağlı yayını, CDN'i, oynatıcıyı ve meta veriyi paylaşan ayrı hatlar olarak tutun.
Mimari diyagram
Diyagram içeriği
- Creator
- Upload API
- Raw uploads
- Transcode jobs
- Transcode workers
- Packager
- Renditions
- Video metadata
- Viewer
- Playback API
- CDN
- DRM license server
- 1. upload URL
- 2. multipart
- 3. done
- ladder
- segments
- ready
- manifest URL
- cache miss
- license
Nasıl okunur:
- Üst şerit, alım: içerik üreticisi yükleme API'sinden bir yükleme URL'si alır (1), parçaları doğrudan ham yükleme kovasına yükler (2) ve tamamlanan yükleme dönüştürme işlerini kuyruğa koyar (3). İşçiler merdiveni kodlar; paketleyici segmentleri sürüm kovasına yazar ve videoyu meta veri deposunda hazır olarak işaretler.
- Alt şerit, oynatma: izleyici oynatma API'sinden bir manifest URL'si ister, sonra segmentleri CDN'den akışla alır. Önbellek ıskalaması sürüm kovasından okur.
- DRM noktalıdır, çünkü yalnızca korumalı içerik buna ihtiyaç duyar: oynatıcı lisans sunucusundan bir lisans alır.
- Markdown bloğu örnek bir merdiven gösterir. Sizin sayılarınız kendi içeriğinizden ve izleyicilerinizin bant genişliğinden gelmeli.
Diyagrama neler koymalı
- Baytların nereden aktığı. Yüklemeleri ve segmentleri API'nizden değil, depolamaya ve CDN'e giderken çizin.
- İş birimi. "Sürüm ve parça başına bir iş", gözden geçirenlere yeniden denemelerin ve paralelliğin nasıl çalıştığını söyler.
- Formatlar ve koruma. HLS, DASH ya da CMAF'ı ve kullanıyorsanız DRM'i adlandırın.
- Hazır sinyali. Bir video paketleme bitene kadar oynatılamaz; bu durumun nerede yaşadığını gösterin.
Aynı kuyruk ve işçi şekli olay güdümlü mimari yazısında da görünür. Bulut tarafı için AWS çok bölgeli mimari diyagramı birden fazla bölgeden sunmayı anlatır; sunucusuz mimari diyagramı da depolama olaylarının bir işçi filosu yerine fonksiyonları nasıl tetikleyebileceğini gösterir.
Archboard'da oluşturun
- Google ya da GitHub ile giriş yapın ve bir diyagram oluşturun.
- İçerik üreticisi ve izleyici için C4 Modeli paketinden iki Kişi düğümü ekleyin.
- Yükleme API'si, dönüştürme işçileri, paketleyici ve oynatma API'si için Konteyner düğümleri ve video meta verisi için bir Veritabanı ekleyin.
- Bulut paketinden iki Nesne depolama düğümü ve bir CDN, dönüştürme işleri için Veri paketinden bir Kuyruk ve DRM lisans sunucusu için bir Harici sistem ekleyin.
- Alımı üst şeride, oynatmayı alt şeride çizin, yükleme adımlarını kenarlarda numaralandırın ve merdiveninizi içeren, Temel paketinden bir Markdown bloğu ekleyin.
Örnek 13 diyagram düğümü kullanıyor ve Free planın sınırları içinde kalıyor.
SSS
Uyarlanabilir bit hızı merdiveni nedir? Bir videonun kodlandığı, her birinin kendi çözünürlüğü ve bit hızı olan sürümler kümesi. Oynatıcı, izleyicinin bağlantısının kaldırabileceği en iyisini seçer ve bant genişliği değiştikçe geçiş yapar.
HLS mi kullanmalıyım, DASH mı? Çoğu zaman ikisini de. Bir kez CMAF segmentleri olarak paketleyin ve bir HLS ile bir DASH manifesti yazın; böylece iki kopya saklamadan Apple cihazlarını ve diğer oynatıcıları kapsarsınız.
Neden doğrudan nesne depolamaya yüklemeli? API sunucularınızdan geçen büyük dosyalar bağlantıları ve belleği meşgul eder; kopan bir bağlantı da yüklemeyi baştan başlatır. Önceden imzalı çok parçalı yüklemeler doğrudan depolamaya gider ve parça parça devam eder.
Dönüştürme nasıl paralelleştirilir? Kaynağı anahtar karelerde parçalara bölün ve her parçayı ve sürümü ayrı bir iş olarak kodlayın, sonra sonuçları birleştirin ya da paketleyin.
Video için CDN gerekli mi? Küçük bir kitlenin ötesindeki her şey için evet. Segmentler statik dosyalardır ve bir CDN tekrarlanan istekleri sizin depolamanızdan değil, izleyicilere yakın önbelleklerden karşılar.