YouTube’da videoları barındırmak, oldukça iyi bir video oynatıcıya sahip olması, serbest bant genişliği desteği vermesi, mobil cihazlarla uyumluluğu, ağ etkileri ve isteğe bağlı olarak hiçbir reklam göstermemesi gibi sağladığı olanaklardan dolayı birçok kullanıcı tarafından tercih edilmektedir. Youtube platformu genel olarak gizlilik seviyesini fazla üst seviyelerde tutmayan bir platformdur. Diğer sağlayıcıların çoğu, ücretsiz reklamları devre dışı bırakma özelliği hariç, benzer niteliklerde hizmet vermektedirler.

Biz bu makalede kendi video’larımızı kendi sanal sunucularımız üzerinde nasıl host edip yayımlarız onu göreceğiz.

Gereksinimler

Öncelikle kuruluma geçmeden önce CloudEOS‘ a kayıt olarak bir adet Ubuntu 16.04 sunucunuzu oluşturmalısınız.

HLS ile Self-Hosting Video Hizmeti Vermek

Html kodlamada <Video> taglaması, etiketi ile bir videoyu kendi sistemin üzerinde barındırmak çok basittir.

<video controls>
<source src="../videos/ornek_video.webm" type="video/webm">
<source src="../videos/ornek_video.mp4" type="video/mp4">
</video>

Bununla birlikte, ekran genişliğine bağlı olarak farklı videolar sunmak mümkün iken, videoyu mevcut bant genişliğine uyarlamak biraz daha zahmetlidir. Bunun için iki çözüm bulunmaktadır.

  • HLS (RFC 8216, informational),
  • MPEG-DASH (ISO/IEC 23009-1:2014)

Her ikisi de uyarlanabilir bit hızı akış protokolleridir. Video küçük parçalara bölünür ve çeşitli bit hızlarında sunulur. Geçerli ağ koşullarına bağlı olarak, player bir sonraki parçayı indirmek için otomatik olarak uygun bit hızını seçmektedir.

HLS, ilk başta Apple tarafından uygulanmış ancak şu an Android’de, Microsoft Edge ve Chrome tarafından da direk desteklenmektedir. hls.js, diğer tarayıcılara HLS desteğini getiren bir JavaScript kütüphanesidir. MPEG-DASH teknik olarak üstündür (codec-agnostik) ancak yalnızca dash.js gibi bir JavaScript kitaplığı üzerinden çalışmaktadır. Her iki durumda da, yerel destek olmadığında medya kaynağı uzantılarının desteği gereklidir. IOS’daki Safari’nin bu özelliği yoktur ve bu nedenle MPEG-DASH’ı kullanamazsınız. Sonuç olarak, en uyumlu çözüm şu an için HLS olarak kabul edilmektedir.

Encode Etme

HLS videolarını sunmak için üç tür dosyaya ihtiyacımız vardır.

  • medya parçaları (farklı bit hızları/çözünürlük ile kodlanmış),
  • medya bölümlerini listeleyen her varyant için bir medya oynatma listesi,
  • medya çalma listelerini listeleyen bir ana çalma listesi

Medya segmentleri iki biçimde olabilir.

  • MPEG-2 Aktarım Akışları (TS),
  • Parçalanmış MP4

Parçalanmış MP4 medya parçaları, iOS 10’dan beri desteklenmektedir. Bunlar biraz daha verimlidir ve MPEG-DASH ile aynı içeriğe hizmet etmek için yeniden kullanılabilirler (yalnızca manifestolar farklıdır). Bununla birlikte, iOS’un eski sürümlerini hedeflemek istiyorsanız, MPEG-2 TS’yi kullanmanız gereklidir.

FFmpeg bir videoyu medya bölümlerine dönüştürebilir ve ilişkili medya oynatma listeleri oluşturabilir. Peer5‘in dökümantasyonu ilgili uygun komutları açıklamaktadır. Tüm adımları birleştiren kullanışlı (Python 3.6) bir video2hls betiğini bir araya getirelim. İlgili video dosyanızda bahsedilen komutları çalıştırdıktan sonra aşağıda listelenmiş olan dosyaları elde etmiş olacaksınız.

  • her çözünürlük için medya segmentleri (1080p_1_001.ts, 720p_2_001.ts, …)
  • her çözünürlük için medya oynatma listeleri (1080p_1.m3u8, 720p_2.m3u8, …)
  • ana çalma listesi (index.m3u8)
  • videonuzun progressive (streamable) MP4 sürümü (progressive.mp4)
  • poster dosyası (poster.jpg)

Komut dosyası, özelleştirme için birçok seçenek kabul eder. Bunları keşfetmek için “–help” flag’ini kullanabilirsiniz. Her bir flag için bir açıklama ile yürütülen “ffmpeg” komutlarını almak için “–debug” ile çalıştırmalısınız. Örneğin, ilgili poster dosyası aşağıdaki komutu çalıştırarak oluşturulabilir.

ffmpeg \
`# istenilen pozisyona getirme (5%)` \
-ss 4 \
`# girdi dosyasını belirleme ` \
-i ../input.mp4 \
`# sadece 1 frame al` \
-frames:v 1 \
`# seçilen I-frame'e ve scale'e göre filtrele` \
-vf 'select=eq(pict_type\,I),scale=1280:720' \
`# Tercih edilen JPEG kalitesi ~ 10` \
-qscale:v 28 \
`# çıktı dosyası` \
poster.jpg

Sunma

Herhangi bir yere yükleyebildiğimiz bir grup statik dosya bulunmaktadır. Ancak iki ayrıntı önemlidir.

  • Başka bir alan adından sunarken, CORS’in GET taleplerine izin verecek şekilde yapılandırılması gerekmektedir. “Access-Control-Allow-Origin: *” eklemek yeterlidir.
  • Bazı istemciler MIME türleri konusunda seçici olabilir. Dosyaların aşağıdaki tabloda olanlar ile sunulduğundan emin olmalısınız.
TürUzantıMIME tipi
Playlists.m3u8application/vnd.apple.mpegurl
MPEG2-TS segments.tsvideo/mp2t
fMP4 segments.mp4video/mp4
Progressive MP4.mp4video/mp4
Poster.jpgimage/jpeg

Dosyalarımızı S3’le uyumlu ve Türkiye’de bulunan Cloudeos’un Nesne Depolama Alanı’nda barındıracağız.

Dosyaları yüklemek için s3cmd kullanıyoruz. Öncelikle, API kimlik bilgilerinizi portaldan kurtarmalı ve “~/.s3cfg” dosyasına koymalısınız.

[default]
host_base = o.cloudeos.com
host_bucket = %(bucket)s.o.cloudeos.com
access_key = .....
secret_key = ....
use_https = True

İkinci adım bir bucket oluşturacağız.

$ s3cmd mb s3://hls-videos
Bucket 's3://hls-videos/' created

Bu bucket için CORS politikasını yapılandırmamız gerektirmektedir. İlk olarak, politikayı bir cors.xml dosyasında tanımlamalıyız (izin verilen origin’i kısıtlamak isterseniz değişiklik yapabilirsiniz).

<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>

Ardından politikayı bucket’a uygulayalım.

$ s3cmd setcors cors.xml s3://hls-videos

Son olarak statik dosyaları kopyalayacağız. Her videoda, oluşturulan tüm dosyaları içeren dizin için aşağıdaki komutu kullanabiliriz.

while read extension mime gz; do
[ -z "$gz" ] || {
# gzip compression (if not already done)
for f in *.${extension}; do
! gunzip -t $f 2> /dev/null || continue
gzip $f
mv $f.gz $f
done
}
s3cmd --no-preserve -F -P \
${gz:+--add-header=Content-Encoding:gzip} \
--mime-type=${mime} \
--encoding=UTF-8 \
--exclude=* --include=*.${extension} \
--delete-removed \
sync . s3://hls-videos/video1/
done <<EOF
m3u8 application/vnd.apple.mpegurl true
jpg image/jpeg
mp4 video/mp4
ts video/mp2t
EOF

Bu dosyalar şu anda “https://hls-videos.o.cloudeos.com/video1/” da erişilebilir halde bulunmaktadır. Bu adres sizin gerçekleştirdiğiniz setup’a göre değişecektir.

HTML

Videomuzu aşağıdaki biçimlendirme ile bir belgeye ekleyebiliriz.

<video poster="https:///hls-videos.o.cloudeos.com/video1/poster.jpg"
controls preload="none">
<source src="https:///hls-videos.o.cloudeos.com/video1/index.m3u8"
type="application/vnd.apple.mpegurl">
<source src="https:///hls-videos.o.cloudeos.com/video1/progressive.mp4"
type='video/mp4; codecs="avc1.4d401f, mp4a.40.2"'>
</video>

Yerli destekli tarayıcılar HLS sürümünü kullanırken diğerleri ileri MP4 sürümüne geri döner. Bununla birlikte, hls.js yardımıyla çoğu tarayıcıya HLS sürümünden de yararlanmalarını sağlayabiliriz.

<script src="https://cdn.jsdelivr.net/npm/hls.js@lastest"></script>
<script>
if(Hls.isSupported()) {
var selector = "video source[type='application/vnd.apple.mpegurl']",
videoSources = document.querySelectorAll(selector);
videoSources.forEach(function(videoSource) {
var once = false;

// Clone the video to remove any source
var oldVideo = videoSource.parentNode,
newVideo = oldVideo.cloneNode(false);

// Replace video tag with our clone.
oldVideo.parentNode.replaceChild(newVideo, oldVideo);

// On play, initialize hls.js, once.
newVideo.addEventListener('play',function() {
if (once) return;
once = true;

var hls = new Hls({ capLevelToPlayerSize: true });
hls.attachMedia(newVideo);
hls.loadSource(videoSource.src);
}, false);
});
}
</script>

Sonuç olarak ilgili dosya kendi sanal sunucumuz üzerinden herhangi bir üçüncü parti video platformuna ihtiyaç duymadan yayımlanmaktadır.

Playerlar bir tarayıcıdan diğerine göre farklılıklar gösterebilmektedir, ancak genel olarak temel ihtiyaçları karşılamaktadır. hls.js aracılığıyla HLS videolarını kullanan “Video.js” veya “MediaElements.js” gibi daha gelişmiş bir player’a geçebilirsiniz.

Bu dokümanda, makalede yazan komutları, çözümleri uygulamak tamamen kullanıcının kendi sorumluluğunda ve insiyatifin de olan bir konudur, mevcut komutların uygulanması ile doğabilecek, oluşabilecek her türlü sorumluluk ve sonuçlar kullanıcının kendisine aittir, CloudEOS’ un bu konuda herhangi bir sorumluluğu bulunmamaktadır.

16 Paylaşımlar