Pencere içinde pencere özelliğini kullanarak video izleme

François Beaufort
François Beaufort

Pencere İçinde Pencere (PIP), kullanıcıların kayan bir pencerede video izlemesine olanak tanır. (her zaman diğer pencerelerin üstünde görünür) olduğundan bu öğeleri takip edebilirler. diğer site veya uygulamalarla etkileşimde bulunurken içerik izleme.

Pencere İçinde Pencere Web API'si ile ağdaki Web sitenizdeki video öğeleri için Pencere İçinde Pencere. Hemen deneyin: resmi Pencere İçinde Pencere örneği.

Arka plan

Safari, Eylül 2016'da WebKit API üzerinden Pencere İçinde Pencere desteği ekledi . Altı ay sonra Chrome otomatik olarak oynatıldı Android O sürümü çıktıktan sonra yerel Android API. Altı ay sonra, kendimizi geliştirmeyi amaçladığımızı Safari'ninkiyle uyumlu bir özellik sunan ve web'e izin veren bir Web API'sini standart geliştiricilerin pencere içinde pencere özelliğiyle eksiksiz bir deneyim oluşturup kontrol etmesini sağlayabilirsiniz. İşte oldu.

Kodu öğrenin

Pencere içinde pencere moduna gir

Bir video öğesiyle ve kullanıcının etkileşime girebileceği bir yolla başlayalım bunu kullanabilirsiniz.

<video id="videoElement" src="https://example.com/file.mp4"></video>
<button id="pipButtonElement"></button>

Pencere içinde pencere özelliğini yalnızca kullanıcı hareketine yanıt olarak isteyin ve taahhüt videoElement.play() tarafından iade edildi. Çünkü vaatler henüz kullanıcı hareketlerini uygulayabilir. Bunun yerine, requestPictureInPicture() öğesini pipButtonElement üzerindeki tıklama işleyiciyi aşağıda gösterildiği gibi görebilirsiniz. Bu sizin sorumluluğunuzdadır ve kullanıcı iki kez tıkladığında ne olacağını.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  await videoElement.requestPictureInPicture();

  pipButtonElement.disabled = false;
});

Vadettiğimiz söz konusu olduğunda Chrome, videoyu küçülterek kullanıcı diğer pencereler arasında gezinebilir ve bu pencerelerin üzerine gelebilir.

Hepsi bu kadar. Tebrikler! Okumayı bırakıp hak ettiğiniz şeyi alabilirsiniz Ne yazık ki bu her zaman geçerli değil. Vaat, herhangi bir durumda reddedilebilir aşağıdakilerden biri olabilir:

  • Pencere içinde pencere özelliği sistem tarafından desteklenmiyor.
  • Dokümanda, kısıtlayıcı nedeniyle Pencere İçinde Pencere kullanımına izin verilmiyor. izinler politikasına bakın.
  • Video meta verileri henüz yüklenmedi (videoElement.readyState === 0).
  • Video dosyası yalnızca ses içeriyor.
  • Yeni disablePictureInPicture özelliği, video öğesinde bulunur.
  • Arama, bir kullanıcı hareketi etkinlik işleyicisinde (ör. düğme tıklaması) yapılmadı. Chrome 74'ten itibaren bu yalnızca Pencere İçinde Pencere zaten mevcut.

Aşağıdaki Özellik desteği bölümünde, bir düğmenin bu kısıtlamalara bağlıdır.

Bu olası hataları yakalamak için bir try...catch bloku ekleyelim ve ne olup bittiğini anlamasını sağlar.

pipButtonElement.addEventListener('click', async function () {
  pipButtonElement.disabled = true;

  try {
    await videoElement.requestPictureInPicture();
  } catch (error) {
    // TODO: Show error message to user.
  } finally {
    pipButtonElement.disabled = false;
  }
});

Video öğesi, pencere içinde pencere veya pencere biçiminde olsun, aynı şekilde davranır. değil: Etkinlikler tetiklenir ve çağrı yöntemleri çalışır. Bölgedeki durum değişikliklerini yansıtır. Pencere İçinde Pencere (oynatma, duraklatma, sarma vb.) ve aynı zamanda JavaScript'te durumun programlı olarak değiştirilmesini sağlar.

Pencere İçinde Pencere modundan çık

Şimdi, düğmemizi Pencere İçinde Pencere moduna girmek ve pencereden çıkmak için düğmemizi yapalım. Biz önce document.pictureInPictureElement salt okunur nesnesinin olup olmadığını kontrol etmem gerekir video öğemizdir. Değilse, giriş yapılması için bir istek Yukarıdaki gibi Pencere İçinde Pencere. Aksi takdirde, document.exitPictureInPicture(). Bu değer, videonun şurada tekrar gösterileceği anlamına gelir: orijinal sekme. Bu yöntemin aynı zamanda bir vaat döndürdüğünü unutmayın.

    ...
    try {
      if (videoElement !== document.pictureInPictureElement) {
        await videoElement.requestPictureInPicture();
      } else {
        await document.exitPictureInPicture();
      }
    }
    ...

Pencere İçinde Pencere etkinliklerini dinleme

İşletim sistemleri, Pencere İçinde Pencere özelliğini genellikle tek bir pencereyle kısıtlar. Chrome'un uygulaması bu kalıbı izler. Yani kullanıcılar yalnızca oyun pencere içinde pencere eklemeniz gerekir. Kullanıcıların çıkış yapmasını beklemeniz gerekir. Siz istemeseniz bile pencere içinde pencere özelliğini kullanabilirsiniz.

Yeni enterpictureinpicture ve leavepictureinpicture etkinlik işleyicileri kullanıcı deneyimi için özelleştirmemize yardımcı oluyor. Bu, bir web sitesine göz atmaktan veya video kataloğundan canlı sohbetlere kadar her şeyi gösterir.

videoElement.addEventListener('enterpictureinpicture', function (event) {
  // Video entered Picture-in-Picture.
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  // Video left Picture-in-Picture.
  // User may have played a Picture-in-Picture video from a different page.
});

Pencere içinde pencere penceresini özelleştirme

Chrome 74, Google Haritalar'da oynat/duraklat, önceki parça ve sonraki parça düğmelerini destekler Media Session API'yi kullanarak kontrol edebileceğiniz Pencere İçinde Pencere penceresi.

Pencere İçinde Pencere penceresinde medya oynatma kontrolleri
Şekil 1. Pencere İçinde Pencere penceresinde medya oynatma kontrolleri
ziyaret edin.
'nı inceleyin.

Varsayılan olarak Pencere İçinde Pencere'de oynat/duraklat düğmesi her zaman gösterilir penceresinde MediaStream nesneleri (ör. getUserMedia(), getDisplayMedia(), canvas.captureStream()) veya videoda bir MediaSource varsa süre +Infinity olarak ayarlanmış olmalıdır (ör. canlı feed). Oynatma/duraklatma düğmesinin her zaman görünür olduğundan, hem "Oynat" için hem de Medya Oturumu işlem işleyicileri ayarlayın ve "Pause" (Duraklat) gerçekleştirebilirsiniz.

// Show a play/pause button in the Picture-in-Picture window
navigator.mediaSession.setActionHandler('play', function () {
  // User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function () {
  // User clicked "Pause" button.
});

"Önceki Parça" gösteriliyor ve "Sonraki parça" benzerdir. Ayar Bu kullanıcılar için Medya Oturumu işlem işleyicileri Pencere İçinde Pencerede gösterilir bu işlemleri gerçekleştirebilirsiniz.

navigator.mediaSession.setActionHandler('previoustrack', function () {
  // User clicked "Previous Track" button.
});

navigator.mediaSession.setActionHandler('nexttrack', function () {
  // User clicked "Next Track" button.
});

Bunun nasıl çalıştığını görmek için resmi Medya Oturumu örneğini deneyin.

Pencere İçinde Pencere pencere boyutunu alma

Video girip çıktığında video kalitesini ayarlamak istiyorsanız Pencere içinde pencere boyutunu bilmeniz ve Kullanıcı pencereyi manuel olarak yeniden boyutlandırırsa bildirim alır.

Aşağıdaki örnekte, Pencere içinde pencere, oluşturulduğunda veya yeniden boyutlandırıldığında.

let pipWindow;

videoElement.addEventListener('enterpictureinpicture', function (event) {
  pipWindow = event.pictureInPictureWindow;
  console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`);
  pipWindow.addEventListener('resize', onPipWindowResize);
});

videoElement.addEventListener('leavepictureinpicture', function (event) {
  pipWindow.removeEventListener('resize', onPipWindowResize);
});

function onPipWindowResize(event) {
  console.log(
    `> Window size changed to ${pipWindow.width}x${pipWindow.height}`
  );
  // TODO: Change video quality based on Picture-in-Picture window size.
}

Her küçük değişiklik yapıldığından doğrudan yeniden boyutlandırma etkinliğine bağlanmamanızı öneririm. farklı bir etkinlik tetikler. Bu durum, her yeniden boyutlandırmada pahalı bir işlem yapıyorsanız performans sorunları yaşanabilir. İçinde başka bir deyişle, yeniden boyutlandırma işlemi etkinlikleri tekrar tekrar tetikler. pek çok yolu vardır. Kısıtlama ve kontrol etme gibi yaygın teknikleri hata ayıklamayı deneyin.

Özellik desteği

Pencere İçinde Pencere Web API'si desteklenmiyor olabilir. Bu nedenle bu durumu tespit etmeniz gerekir. sağlayabilirsiniz. Desteklendiğinde bile veya bir izin politikası tarafından devre dışı bırakılmış olabilir. Neyse ki yeni boole document.pictureInPictureEnabled değerini kullanın.

if (!('pictureInPictureEnabled' in document)) {
  console.log('The Picture-in-Picture Web API is not available.');
} else if (!document.pictureInPictureEnabled) {
  console.log('The Picture-in-Picture Web API is disabled.');
}

Bir video için belirli bir düğme öğesine uygulandığında, pencere içinde pencere düğmenizin görünürlüğünü kontrol altında tutun.

if ('pictureInPictureEnabled' in document) {
  // Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton();
  videoElement.addEventListener('loadedmetadata', setPipButton);
  videoElement.addEventListener('emptied', setPipButton);
} else {
  // Hide button if Picture-in-Picture is not supported.
  pipButtonElement.hidden = true;
}

function setPipButton() {
  pipButtonElement.disabled =
    videoElement.readyState === 0 ||
    !document.pictureInPictureEnabled ||
    videoElement.disablePictureInPicture;
}

MediaStream video desteği

MediaStream nesneleri (ör. getUserMedia(), getDisplayMedia(), canvas.captureStream()), Chrome 71'de Pencere İçinde Pencere'yi de destekler. Bu kullanıcının web kamerasını içeren bir Pencere İçinde Pencere penceresi gösterebileceğiniz anlamına gelir. video akışı, görüntülü video akışı ve hatta bir tuval öğesi. Lütfen giriş için video öğesinin DOM'ye eklenmesi gerekmez. Aşağıda gösterildiği gibi Pencere İçinde Pencere'yi seçin.

Kullanıcının web kamerasını Pencere İçinde Pencere penceresinde göster

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

Pencere içinde pencere penceresinde ekranı göster

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({video: true});
video.play();

// Later on, video.requestPictureInPicture();

Tuval öğesini Pencere İçinde Pencere penceresinde gösterme

const canvas = document.createElement('canvas');
// Draw something to canvas.
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);

const video = document.createElement('video');
video.muted = true;
video.srcObject = canvas.captureStream();
video.play();

// Later on, video.requestPictureInPicture();

canvas.captureStream() özelliğini Media Session API ile birleştirerek Örneğin, Chrome 74'te bir ses oynatma listesi penceresi oluşturun. Resmi web sitesine göz atın Ses oynatma listesi örneği.

Pencere içinde pencere penceresinde ses oynatma listesi
Şekil 2. Pencere içinde pencere penceresinde ses oynatma listesi
ziyaret edin.
'nı inceleyin.

Örnekler, demolar ve codelab'ler

Pencere içinde pencere özelliğini denemek için resmi Pencere İçinde Pencere örneğimize göz atın. Web API'si.

Ardından demolar ve codelab'ler gelir.

Sırada ne var?

Öncelikle uygulama durumu sayfasına göz atarak API şu anda Chrome ve diğer tarayıcılarda uygulanmaktadır.

Yakın gelecekte aşağıdaki değişiklikleri göreceksiniz:

Tarayıcı desteği

Pencere İçinde Pencere Web API'si Chrome, Edge, Opera ve Safari'de desteklenir. Ayrıntılar için MDN bölümüne bakın.

Kaynaklar

Mounir Lamouri ve Jennifer Apacible'a Pencere İçinde Pencere ve bu makaleyle ilgili yardım. Herkese teşekkür ederim. standartlaştırma çabasına dahil edilir.