Hls.js ile Kaydırmaya Duyarlı Video Ön Yükleme Penceresi Nasıl Oluşturulur?

Hls.js ile Kaydırmaya Duyarlı Video Hls.js ile Kaydırmaya Duyarlı Video kapsamında, TL;DR Dikey video beslemeleri ilk öğede hızlıdır ve her öğede kesintiye uğrar. Kaydırma yönünü izleyen, hls.js kaynaklarını kullanıcıdan önce ekran dışı öğelere ekleyen ve Safari'nin…

5
Paylaş
Hls.js ile Kaydırmaya Duyarlı Video Ön Yükleme Penceresi Nasıl Oluşturulur?

Hls.js ile Kaydırmaya Duyarlı Video

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, TL;DR Dikey video beslemeleri ilk öğede hızlıdır ve her öğede kesintiye uğrar. Kaydırma yönünü izleyen, hls.js kaynaklarını kullanıcıdan önce ekran dışı öğelere ekleyen ve Safari’nin video öğesi tavanının altında kalmanız için pencerenin dışındaki her şeyi yırtan bir önyükleme penceresi oluşturacağız. Uzlaştırıcı desen, ~120 satır. Sorunlu Öğe 1, sayfa etrafına yüklendiğinden anında oynatılıyor.

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, Öğe 2 siyahı, ardından bir döndürücüyü ve ardından düşük kaliteye doğru bir kekemeliği gösterir. Her şeyin önceden yüklenmesi takılmayı düzeltir ve bunun yerine iPhone’da bir veri planı yangını ve çökme getirir. İstediğimiz şey: kullanıcının kaydırma yaptığı yönde az sayıda öğeyi önceden yüklemek ve geri kalan her şeyi agresif bir şekilde serbest bırakmak. 1.

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, preload=’auto’ neden bir strateji değildir Tarayıcılar önyüklemeyi bir öneri olarak ele alır ve mobil tarayıcılar, kullanıcının verilerini korumak için kasıtlı olarak bunu en az ciddiye alır. HLS ile gerçek kontrole sahip olursunuz çünkü yükleme JS’de gerçekleşir. hls.js’de kaynak eklemek tetikleyicidir.

Tasarım ve teknik ayrıntılar

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, Bir örneğin bir bildirim URL’si olduğu anda, oynatma listesini getirir ve görünüm alanı olsun ya da olmasın, segmentleri çekmeye başlar. Bu bizim ilkelimiz. npm i hls.js@^1.7.0 2. İki modlu bir oynatıcı sarmalayıcısı 🎛️ Ekran dışı öğeler sığ bir ara belleğe ihtiyaç duyar. Başlamak için yeterli. Aktif öğe normal olanı alır.

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, // feed/player.js (hls.js 1.7.x) ithalat “hls.js”den Hls; const PRELOAD_CONFIG = { // birinci kareyi oluşturmak için yeterli, bir veri planını yakmak için yeterli değil maxBufferLength: 4, maxMaxBufferLength: 6, // medya eklenmeden önce 1.

Hls.js ile Kaydırmaya Duyarlı Video

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, parçayı alın startFragPrefetch: doğru, autoStartLoad: doğru, }; const ACTIVE_CONFIG = { maxBufferLength: 30, // hls.js varsayılanı maxMaxBufferLength: 60, startFragPrefetch: doğru, autoStartLoad: doğru, }; dışa aktarma işlevi add(videoEl, url, { active = false } = {}) { if (videoEl.canPlayType(“application/vnd.apple.mpegurl”)) { // Safari, HLS’yi yerel olarak oynatır; yönetilecek hls.js örneği yok videoEl.src = url; videoEl.preload = aktif ?

Bugünden bakınca ne kadar güvenilir?

Hls.js ile Kaydırmaya Duyarlı Video kapsamında, “otomatik” : “meta veriler”; return { native: true, destroy: () => { videoEl.removeAttribute(“src”); videoEl.load(); } }; } const hls = new Hls(aktif ? ACTIVE_CONFIG : PRELOAD_CONFIG); hls.loadSource(url); hls.attachMedia(videoEl); dönüş { yerli: yanlış, selam, yok et: () => { hls.destroy(); }, }; } 💡 İpucu: hls.js’de maxBufferLength varsayılan olarak 30’dur. İzlenen öğe için otuz saniye mantıklıdır.

Sıradaki dört öğenin her biri için otuz saniye değildir. 3. Yönlü pencere Saf pencere simetriktir: 2 önce, 2 sonra. Ancak kaydırma simetrik değildir. Aşağı inen biri aşağı doğru ilerlemeye devam ediyor ve arkasındaki öğe az önce bitirdiği öğe oluyor.

// feed/window.js const İLERİ = 4; // seyahat yönünde önceden yüklenecek öğeler const ARKASINDA = 1; // hızlı geri kaydırma için ucuz sigorta /* @param {sayı} dizini geçerli etkin öğe @param {1|-1} yön 1 = aşağı kaydırma, -1 = yukarı kaydırma @param {number} toplam öğe sayısı @, bir kaynağın eklenmesi gereken {Set} indeksini döndürür / dışa aktarma işlevi arzu edilenPencere(dizin, yön, toplam) { sabit lo = yön === 1 ?

Okuyucu için pratik anlamı

dizin – ARKASINDA : dizin – ÖNDE; const hi = yön === 1 ? indeks + ÖNDE : indeks + ARKADA; const out = yeni Küme(); for (let i = Math.max(0, lo); i <= Math.min(toplam – 1, hi); i++) out.add(i); geri dön; } Aynı bant genişliği bütçesi, isabet oranının kabaca iki katı. Bir şartlı. 4. Uzlaştırıcı (önemli kısım burası) 🔑 Aksi halde göndereceğiniz hata şu: Bir kullanıcı altı öğeyi hızlıca kaydırıyor.

Kaydırma sırasında ön yükleme tetiklenir, dışarı kaydırma sırasında sökme tetiklenir ve bunlar birbiriyle yarışan bağımsız efektler olduğundan, önceden yüklemeye karar verdiğiniz bir oyuncuyu yerle bir edersiniz. Belirti: Yavaş kaydırdığınızda sorun yok, hızlı kaydırdığınızda bozuluyor. Geliştirme konusunda iyi, vahşi doğada bozuk.

Düzeltme: Hiçbir zaman ön yükleme ve sökme işlemlerini ayrı efektler olarak tetiklemeyin. İstenilen seti hesaplayın, ektekiyle karşılaştırın, farka göre hareket edin.

// feed/reconciler.js “./player.js” dosyasından {attach }’i içe aktarın; “./window.js” dosyasından { arzu edilenWindow } dosyasını içe aktarın; dışa aktarma işlevi createFeedController({ items, getVideoEl }) { const ekli = yeni Harita(); // indeks -> { yerel, hls, yok et, aktif } lastIndex = 0 olsun; işlev uzlaştırma (dizin) { c onst yön = indeks >= lastIndex ?

1 : -1; lastIndex = dizin; const want = istenenPencere(indeks, yön, öğeler.uzunluk); // 1. pencerenin dışındaki her şeyi serbest bırakın for (eklinin const [i, tanıtıcısı]) { if (!want.has(i)) { tanıtıcı.destroy(); ekli.delete(i); } } // 2.

Henüz içinde olmayan her şeyi ekleyin for (istek sabiti) { const el = getVideoEl(i); if (!el) devam ederse; // henüz oluşturulmadı, atla const mevcut = ekli.get(i); const mustBeActive = i === indeks; eğer (mevcut) { // yeni etkin olan öğeyi derin arabellek yapılandırmasına yükselt if (shouldBeActive && !existing.active) { mevcut.destroy(); eklenmiş.set(i, { …attach(el, items[i].hlsUrl, { active: true }), active: true }); } devam etmek; } ekli.set(i, { …attach(el, items[i].hlsUrl, { active: ShouldBeActive }), aktif: ShouldBeActive, }); } } fonksiyon yokediciHepsi() { for (const [, h] of ekli) h.destroy(); ekli.clear(); } return { uzlaştır, Tümünü yok et, boyutu al() { return ekli.boyut; } }; } Etkin dizini size söyleyen her şeyden yararlanın.

CSS kaydırma yakalama özelliğinde IntersectionObserver yeterlidir: // feed/index.js const denetleyici = createFeedController({ items, getVideoEl: (i) => els[i] }); const io = new IntersectionObserver((girişler) => { for (girişlerin toplamı) { if (e.kesişme Oranı > 0,6) { denetleyici.reconcile(Sayı(e.target.dataset.index)); } } }, { eşik: [0,6] }); eller .forEach((el) => io.observe(el)); 5.

iOS Mobile’da sökme işlemi isteğe bağlı değildir Safari’nin yaklaşık 16 eşzamanlı video öğesinden oluşan geniş çapta bildirilen bir tavanı vardır; bunun ötesinde, diğer olanlar siyaha dönüşür. Bu açıkça belgelenmiş bir API sınırı değil, insanların çarpmaya devam ettiği bir duvar. Her öğe için bir oyuncuyu bağlayan ve hiçbir zaman bağlantısını kesmeyen sonsuz bir akışta, hızlı bir şekilde vurursunuz.

Pencere kapak bağlantılarımız ÖN + ARKA + 1 = 6’da rahatça altına alınır. Ancak öğeyi değil kaynağı serbest bırakın: // DOM düğümünü takılı tutun, medyayı bırakın tanıtıcı.destroy(); // hls.destroy() tamponları + kod çözücüyü serbest bırakır // öğe, geri kaydırma sırasında ucuz yeniden ekleme için listede kalır. Bileşenin bağlantısının kesilmesi de geri kaydırmanın tüm düzen maliyetini ödediği anlamına gelir.

Kabuğu saklayın, medyayı tek kullanımlık hale getirin. ⚠️ Çoklu eşzamanlı video öğeleri, öğe sayısının ötesinde bir bellek ve GPU basıncı sorunudur. Yakalanabilir bir hata değil, bir kilitlenme olarak görünüyor, bu nedenle onu tespit edip geri çekilemezsiniz. İnşaat nedeniyle çizginin altında kalmak zorundasınız. 6. Kullanıcıların hissettiklerini ölçün 📊 Ölçü, kaydırmanın yerleşmesinden 2.

öğe ve sonrasında ilk karenin boyanmasına kadar geçen süredir. Öğe 1 bir sayfa yüklemesidir ve sizi gururlandırır.

// feed/metrics.js const marks = yeni Harita(); dışa aktarma işlevi markScrollSettled(index) { marks.set(index, performans.now()); } dışa aktarma işlevi markFirstFrame(index, videoEl) { videoEl.addEventListener(“oynuyor”, () => { sabit t0 = işaretler.g et(indeks); if (t0 == null) return; const ms = Math.round(performans.now() – t0); marks.delete(indeks); navigator.sendBeacon?.(“/metrics/feed-ttff”, JSON.stringify({ dizin, ms, pozisyon: indeks, // 40.

madde 2. maddeden daha önemli bağlantı: navigator.connection?.effektifType ?? “bilinmiyor”, })); }, { bir kez: doğru }); } Oturum başına bayt sayısına göre grafiğini çıkarın. Bunlar zıt yönlerde hareket eder ve tek başına ayar yapmak, wifi üzerinde güzel ve telefon planında düşmanca bir şey ortaya çıkarır. İstediğiniz pencere boyutu, ilk kareye kadar geçen sürenin düz gittiği en küçük AHEAD boyutudur.

4’ten başlayın, 2’ye kadar yürüyün ve eğrinin nerede kıvrıldığını izleyin. Düz noktayı geçtikten sonra hiçbir şey satın almıyorsunuz ve başkasının parasını harcıyorsunuz. 💡 İpucu: Eğer besleme on öğe için anlıksa ve sonrasında bozulursa, yırtma işleminiz devam etmiyor demektir. Daha fazla önyükleme sorunu çözmez.

Sırada ne var hls.js henüz birinci sınıf bir “ekran dışında N saniye önceden yükleme ve ardından durdurma” API’sini kullanıma sunmuyor. Bunun için açık bir sorun ve ilgili çok bölümlü bir ön alım teklifi var. İzlemeye değer; Yukarıdaki örnek başına maxBufferLength numarası pratik bir alternatiftir.

Ön yükleme maliyetinin azalması için ekran dışı öğelere daha düşük yorumlamalı bir ilk segment sunun, ardından öğe etkinleştiğinde ABR’nin yükselmesine izin verin. Feed’iniz web yerine React Native ise aynı pencere/uzlaştırıcı mantığı geçerlidir. Mux, kaydırma yönüne göre ön yükleme yapan ve yapının doğrudan aktarıldığı bir yayın yazdı.

genel ders: “anında hissettirmek”, işleme probleminin kıyafetlerini giyen bir planlama problemidir. Daha hızlı yüklemiyorsunuz, daha erken yüklüyorsunuz ve zanaat iyi tahmin edip hızla pes ediyor.

Ek okuma: MDN Web Docs

Editörün Notu

Kaydırma yönüne göre ön yükleme stratejisi, kullanıcı deneyimini artırırken cihaz kaynaklarını etkin kullanmayı sağlar; bu sayede gereksiz veri tüketimi ve performans sorunlarının önüne geçebilirsiniz. 2026 itibarıyla mobil tarayıcılarda bu yöntemin avantajları daha da belirgin hale gelecektir.

Emre Demir
Yazar

Yazılım Editörü

Yazılım editörü ve full-stack geliştirici. Uygulama incelemeleri, kodlama rehberleri ve verimlilik araçları üzerine yazıyor. Açık kaynak projelere katkıda bulunuyor; karmaşık konuları yeni başlayanların anlayacağı şekilde anlatmaya özen gösteriyor.

Tüm yazıları gör →