Seringkali video di bioskop online memiliki rasio aspek yang berbeda dengan monitornya. Oleh karena itu, terkadang ada keinginan untuk membuat skala keseluruhan sedikit lebih besar dengan memotong sedikit di bagian tepinya. Atau bahkan - sesuaikan gambar dengan ukuran layar di sisi yang lebih kecil dari gambar. Ini terutama berlaku untuk layar kecil, serta untuk monitor 4: 3 yang lebih lama. Saya masih bungkam tentang fakta bahwa video asli secara umum dapat direntangkan ke satu sisi dan hal ini perlu diperbaiki.
Untuk mengatasi masalah ini, saya memutuskan untuk menulis ekstensi browser untuk Chrome dan Firefox. Idenya begini: saat memutar video browser apa pun, menu di layar akan dipanggil, yang memungkinkan Anda mengubah skala dan rasio aspek gambar secara sewenang-wenang.
iframe
Masalah pertama yang saya hadapi adalah bahwa video di situs web tidak selalu terletak di halaman utama, tetapi dapat disembunyikan jauh di dalam iframe bersarang. Saya memutuskan untuk memindai semua iframe dan menemukan semua elemen video di setiap iframe. Ngomong-ngomong, ini juga memecahkan masalah lain - Anda tidak pernah tahu di mana video iklannya, dan di mana film itu sendiri. Mari kita temukan semuanya dulu.
Fungsi getVideos memanggil dirinya sendiri secara rekursif hingga semua elemen video ditemukan di iframe terakhir. Semua video ditambahkan ke array ap_ext_space.videos. Fungsi getVideos mengambil dokumen dari halaman saat ini sebagai parameter input. Pada peluncuran pertama, dokumen utama diambil Sepanjang jalan, penangan digantung di setiap video, tetapi lebih dari itu di bawah.
getVideos: function (srcDoc) {
if (!srcDoc) {
srcDoc = document;
window.onkeydown = function (event) {
var e = event || window.event;
ap_ext_space.keyDn(e);
};
};
var els = srcDoc.getElementsByTagName('video');
for (var i = 0; i < els.length; i++) {
els[i].addEventListener("seeked", function () {ap_ext_space.zoomw(); console.log('seeked'); }, true);
els[i].addEventListener("abort", function () {ap_ext_space.zoomw(); console.log('abort'); }, true);
els[i].addEventListener("pause", function () {ap_ext_space.zoomw(); console.log('pause'); }, true);
els[i].addEventListener("play", function () {ap_ext_space.zoomw(); console.log('play'); }, true);
els[i].addEventListener("playing", function () {ap_ext_space.zoomw(); console.log('playing'); }, true);
els[i].addEventListener("seeked", function () {ap_ext_space.zoomw(); console.log('seeked'); }, true);
ap_ext_space.videos.push(els[i]);
ap_ext_space.menu(els[i], srcDoc);
};
console.log('all videos:', ap_ext_space.videos);
var ifrs = srcDoc.getElementsByTagName("iframe");
console.log('iframes:', ifrs);
var ifr;
for (var i = 0; i < ifrs.length; i++) {
ifr = ifrs[i];
try {
var innerDoc = (ifr.contentDocument || ifr.contentWindow.document);
var innerWindow = (ifr.contentWindow || ifr);
innerWindow.onkeydown = function (event) {
var e = event || window.event;
ap_ext_space.keyDn(e);
};
ap_ext_space.getVideos(innerDoc);
} catch (err) {
console.log('err', err);
};
};
},
Menu OSD

Oke, kami memiliki daftar semua elemen video. Sekarang bagaimana cara menampilkan menu OSD? Mari kita tambahkan elemen bloknya ke setiap video. Ya, maka kita akan memiliki banyak menu di layar, tetapi pada satu waktu hanya satu video yang ditampilkan: salah satu iklan atau film itu sendiri. Dan hanya satu menu yang akan ditampilkan bersama mereka.
Video biasanya terletak di div induk. Mari tambahkan elemen menu div ke dalamnya sebagai anak terakhir. Dengan demikian, OSD akan selalu ditampilkan di atas video.
Kami akan menyandikan gambar OSD dalam base64 dalam format png dengan saluran alfa transparan dan menempatkannya di ap_ext_space.imgUR, karena browser tidak akan mengizinkan kami memuat gambar dari domain lain. Buat menu untuk setiap video:
menu: function(videoEl, doc) {
// div video
// , ( menuInside)
var els = videoEl.parentNode.getElementsByTagName('div');
var menuInside = false;
for (var j = 0; j < els.length; j++) {
if (els[j].id == 'ap_ext_space_container') {
menuInside = true;
ap_ext_space.menus.push(els[j]);
};
};
if (menuInside == false) {
//
var div = doc.createElement('div');
div.innerHTML = ap_ext_space.html();
videoEl.parentNode.appendChild(div);
div.style.width = '520px';
div.style.height = '410px';
div.style.display = 'block';
div.style.position = 'absolute';
div.id = 'ap_ext_space_container';
var url = "url('" + ap_ext_space.imgURL + "')";
div.style.backgroundImage = url;
div.style.opacity = 0.95;
ap_ext_space.menus.push(div);
//
div.addEventListener("dblclick", function(e) {
e.preventDefault();
e.stopPropagation();
}, true);
div.addEventListener("mouseover", function(e) {
e.preventDefault();
e.stopPropagation();
var elem, evt = e ? e : event;
if (evt.srcElement) {
elem = evt.srcElement;
} else if (evt.target) {
elem = evt.target;
};
//
var pos = {
ap_ext_space_num7: [520 + 134, 82],
ap_ext_space_num8: [520 + 134 + 90, 82],
ap_ext_space_num9: [520 + 134 + 90 + 90, 82],
ap_ext_space_num4: [520 + 134, 82 + 90],
ap_ext_space_num5: [520 + 134 + 90, 82 + 90],
ap_ext_space_num6: [520 + 134 + 90 + 90, 82 + 90],
ap_ext_space_num1: [520 + 134, 82 + 90 + 90],
ap_ext_space_num2: [520 + 134 + 90, 82 + 90 + 90],
ap_ext_space_num3: [520 + 134 + 90 + 90, 82 + 90 + 90]
};
var key, el;
for (var j = 1; j < 10; j++) {
key = 'ap_ext_space_num' + j;
if (elem.id == key) {
elem.style.backgroundImage = "url('" + ap_ext_space.imgURL + "')";
elem.style.backgroundPosition = -pos[key][0] + 'px ' + -pos[key][1] + 'px';
};
};
}, true);
div.addEventListener("mouseout", function(e) {
e.preventDefault();
e.stopPropagation();
var elem, evt = e ? e : event;
if (evt.srcElement) {
elem = evt.srcElement;
} else if (evt.target) {
elem = evt.target;
};
var key, el;
for (var j = 1; j < 10; j++) {
key = 'ap_ext_space_num' + j;
if (elem.id == key) {
elem.style.backgroundImage = "none";
};
};
}, true);
div.addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
var elem, evt = e ? e : event;
if (evt.srcElement) {
elem = evt.srcElement;
} else if (evt.target) {
elem = evt.target;
};
ap_ext_space.clickHandler(elem);
}, true);
div.addEventListener("touchstart", function(e) {
e.preventDefault();
e.stopPropagation();
var elem, evt = e ? e : event;
if (evt.srcElement) {
elem = evt.srcElement;
} else if (evt.target) {
elem = evt.target;
};
ap_ext_space.clickHandler(elem);
}, true);
div.addEventListener("touchend", function(e) {
e.preventDefault();
}, true);
div.addEventListener("touchmove", function(e) {
e.preventDefault();
}, true);
// ( )
ap_ext_space.menuPos();
};
console.log('all menus:', ap_ext_space.menus);
},
Jika Anda menambahkan div OSD ke video seperti ini: videoEl.parentNode.appendChild (div), itu akan muncul di atas video bahkan dalam mode layar penuh. Tetap hanya untuk memusatkannya, atau lebih tepatnya, melakukannya dengan semua item menu blok yang dilampirkan ke elemen video (ukurannya 520x410):
menuPos: function() {
if (ap_ext_space.isFullScreen()) {
var sc = ap_ext_space.scale;
var iw = window.innerWidth,
ih = window.innerHeight;
var w = iw * sc;
var h = w / 16 * 9;
for (var i = 0; i < ap_ext_space.menus.length; i++) {
ap_ext_space.menus[i].style.marginLeft = (iw - 520) / 2 + 'px';
ap_ext_space.menus[i].style.marginTop = (-h - 410) / 2 + 'px';
};
} else {
ap_ext_space.scale = 1;
for (var i = 0; i < ap_ext_space.menus.length; i++) {
ap_ext_space.menus[i].style.marginLeft = '0px';
ap_ext_space.menus[i].style.marginTop = '0px';
};
};
},
isFullScreen: function() {
return !!(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
},
Ngomong-ngomong, pada akhirnya, saya memutuskan untuk menyembunyikan menu sepenuhnya dalam mode berjendela dan hanya mengizinkan kontrol ukuran video dalam mode layar penuh. Di jendela, itu tidak masuk akal.
Penangan
Di sini, saya pikir, semuanya jelas. Pada setiap tombol menu di layar, click handler, gerobak dorong, dan juga menekan kombinasi tombol yang sesuai digantung untuk mengontrol video bahkan dengan menu tersembunyi. Tombol mengontrol nilai skala: ap_ext_space.scale, ap_ext_space.scalew dan ap_ext_space.scaleh, meningkatkan atau menurunkan nilai-nilai ini, dan kemudian mengubah ukuran setiap elemen video yang ditemukan di atas sebagai berikut:
var sc = ap_ext_space.scale;
var iw = window.innerWidth,
ih = window.innerHeight;
var w = iw * sc;
var h = w / 16 * 9;
for (var i = 0; i < ap_ext_space.videos.length; i++) {
el = ap_ext_space.videos[i];
el.style.position = 'initial';
el.style.width = (w) + 'px';
el.style.height = (h) + 'px';
el.style.marginLeft = -(w - iw) / 2 + 'px';
el.style.marginTop = -(h - ih) / 2 + 'px';
el.style.transform = 'scaleX(' + ap_ext_space.scalew + ') scaleY(' + ap_ext_space.scaleh + ')';
};
Selain itu, saya juga bergantung pada penangan acara video yang dicari, batalkan, jeda, putar, putar, dicari pada setiap elemen video (dalam fungsi getVideos () di atas) panggilan ke satu-satunya fungsi yang menggambar ulang menu di layar dengan menghitung ulang koordinatnya, karena terkadang itu "meninggalkan" dengan beberapa tindakan pengguna. Saya melakukan hal yang sama untuk acara pengubahan ukuran jendela browser.
Namespace
Secara umum, ap_ext_space macam apa ini? Faktanya adalah bahwa semua fungsi yang digunakan untuk mengubah ukuran video harus disematkan di halaman yang sesuai (baik di halaman utama atau di iframe). Jadi saya hanya menggabungkan fungsi-fungsi ini dan, bersama mereka, latar belakang OSD base64 menjadi satu namespace. Semua ini dimasukkan ke dalam kode tab browser saat ini dari skrip latar belakang sebagai berikut:
var codeString = ap_ext_space_f.toString() + '; ap_ext_space_f(); ap_ext_space.init()';
chrome.tabs.executeScript({
code: codeString
});
function ap_ext_space_f() {
ap_ext_space = {
init: function() {
//...
},
//...
};
};
Nah, di dalam ap_ext_space, pencarian semua iframe dipicu, lalu semua video di dalamnya, menu di layar dengan penangan dibuat, dan seterusnya.
Cara Penggunaan
Putar video. Klik pada ikon ekstensi. Luaskan video ke layar penuh. Sesuaikan skala dan rasio aspek. Menu dapat disembunyikan dengan shortcut keyboard ctrl + 0.
Hasil
Ekstensi ini disebut Browser Video Tuner, gratis dan saat ini tersedia di toko ekstensi Chrome dan Firefox. Juga, tentu saja, ini dapat dipasang di semua browser yang kompatibel dengan Chrome seperti Opera, Browser Yandex, dan sebagainya. Perlu dicatat bahwa ekstensi tidak berfungsi di semua situs video. Jika akses ke elemen iframe dari luar dilindungi oleh kebijakan keamanan, maka tidak ada video yang akan ditemukan begitu saja. Dan peringatan terkait tentang ini akan muncul di konsol. Dalam kasus ini, menu tidak akan ditampilkan. Tetapi di Youtube dan banyak bioskop online, semuanya berfungsi.
Masalah kecil ditemukan dengan beberapa browser. Misalnya, di Browser Yandex, gambar yang ditampilkan entah bagaimana memburuk dan menyerupai jpeg yang sangat terkompresi. Tetapi ini tidak memengaruhi fungsionalitas dengan cara apa pun.

Saya sedang mencari cara untuk menampilkan menu di layar dalam mode layar penuh hanya di atas seluruh dokumen tanpa menyematkannya di dalam iframe, agar tidak bergantung pada kebijakan keamanan browser, dan mencoba mengontrol ukuran seluruh dokumen secara keseluruhan, tetapi sejauh ini saya belum berhasil. Saya kira ke depan perluasan tersebut akan dilengkapi dengan fungsi-fungsi baru.