Всем привет! Недавно публиковал статью о создании браузерного расширения для скачивания любого видео загруженного во ВКонтакте в любом из доступных качеств.
На тот момент всё ограничилось возможностью скачивания лишь с мобильной версии сайта, так как из неё проще всего вытащить прямые ссылки на .mp4 файлы. Впрочем, не буду повторять всё то, что было сказано в первой статье. Настоятельно рекомендую потратить несколько минут и сначала прочесть её, а затем вернуться сюда. Иначе Вы рискуете не понять некоторых моментов и можете посчитать данную статью поверхностной.
На этом со вступлением всё. Перейдём к сути. Вчера у меня всё же дошли руки до того, чтобы заставить расширение работать и на полной версии сайта. И вот как я это сделал.
Выясняем как всё устроено
В предыдущий раз алгоритм действий был следующим:
Смотрим в исходный код страницы
Видим в нём тег
<video>
со вложенными тегами<source>
Вытаскиваем ссылки на файлы интересующего нас формата
Мы великолепны
Попробовав повторить эти пункты мы зависнем на втором, обнаружив вот это:
<div class="videoplayer">
<div class="videoplayer_media">
<video src="blob:https://vk.com/ca08cc90-10c4-444f-a1bd-004ef4a2057d"></video>
</div>
</div>
Да, никаких привычных глазу форматов, только Binary Large Object. Если не вдаваться в детали — мы имеем дело с потоковым видео, которое отдаётся сервером в режиме реального времени небольшими чанками. Этот Большой Бинарный Объект и есть один из таких чанков.
Существуют способы скачивания подобных данных, в том числе с помощью такого софта как ffmpeg и VLC Media Player, но мы ведь не хотим этим заниматься, правда? Переключиться на мобильную версию VK и скачать видео с неё — дело пары кликов, а мы хотим упростить процесс, а не усложнять его.
Немного пошевелив мозгами и поглядев на монструозные исходники фронтенда VK я пришёл к мысли, что где-то ссылки на .mp4 файлы всё же должны храниться. Нутром чую, что должны. Не особо надеясь на положительный исход я приступил к поискам и через 10-15 минут они увенчались успехом.
Давайте запустим любое видео и выведем в консоль браузера один интересный объект: window.mvcur.player.vars
. Среди десятков его полей будут в том числе вот такие:
{
"url360": "https://vkvd39.mycdn.me/...type=1&...",
"url480": "https://vkvd39.mycdn.me/...type=2&...",
"url720": "https://vkvd39.mycdn.me/...type=3&..."
}
Такие знакомые ссылки с таким знакомым параметром type. Замечательно. Переходим к следующему шагу.
Вырываемся из клетки
Казалось бы — бери ссылки, отображай их под видео и дело сделано. Но не всё так просто. Скрипты каждого отдельного браузерного расширения выполняются в так называемом изолированном окружении. Они не имеют доступа к уже существующим на странице JavaScript-объектам и каким-либо данным из других расширений. Чтобы "достучаться" до нужных нам свойств объекта window
мы выполним JavaScript-инъекцию.
Для начала добавим в manifest.json правило, для исполнения содержимого файла scripts/desktop.js при переходе на любую страницу на домене vk.com:
"content_scripts": [
{
"js": ["scripts/desktop.js"],
"matches": ["https://vk.com/*"],
"run_at": "document_idle"
}
]
Также дадим расширению доступ к файлу со скриптом, инъекцию которого мы будем осуществлять:
"web_accessible_resources": [
{
"resources": ["scripts/desktop-injection.js"],
"matches": ["https://vk.com/*"]
}
]
Реализуем элементарную инъекцию:
// scripts/desktop.js
const script = document.createElement('script');
script.charset = 'utf-8';
script.type = 'text/javascript';
script.src = chrome.runtime.getURL('scripts/desktop-injection.js');
document.querySelector('body').appendChild(script);
// scripts/desktop-injection.js
(() => {
alert('скрипт (кродеться)');
})();
Достигаем цели
Извлечём ссылки на видео и скомпонуем их в точно такой же блок, как и в мобильной версии VK:
// scripts/desktop-injection.js
let videoSources = {
'144p': window.mvcur.player.vars.url144,
// Все остальные качества
'2160p': window.mvcur.player.vars.url2160
};
const label = document.createElement('span');
label.innerText = 'Скачать:';
label.style.marginRight = '2px';
const panel = document.createElement('div');
panel.id = 'vkVideoDownloaderPanel';
panel.appendChild(label);
for (const [quality, url] of Object.entries(videoSources)) {
if (typeof url !== 'undefined') {
const aTag = document.createElement('a');
aTag.href = url;
aTag.innerText = quality;
aTag.style.margin = '0 2px';
panel.appendChild(aTag);
}
}
Невырвиглазно отобразим на странице:
// scripts/desktop-injection.js
/*
* Не под всеми видео есть блок с названием.
* Если он есть - располагаем ссылки над ним.
* Иначе - над блоком с кнопками лайка, репоста и т.п.
* Таким образом ссылки всегда будут находиться сразу под плеером.
*/
const videoTitleBlock = document.querySelector('div.mv_title_wrap');
if (videoTitleBlock) {
panel.style.margin = '8px 0';
videoTitleBlock.before(panel);
} else {
panel.style.margin = '8px 15px';
document.querySelector('div.mv_actions_block').before(panel);
}
Весь код в scripts/desktop.js по сути идентичен тому, что использовался для мобильной версии VK в первой статье: мониторинг отрисовки контейнера плеера, "переходов" между страницами и т. д. Добавил разве что дополнительный логический флаг, чтобы функция парсинга и отображения ссылок не вызывалась более одного раза да немного изменил механизм определения того, находимся ли мы на странице с видео.
Ознакомиться с полным исходным кодом и скачать расширение можно в репозитории на моём GitHub. Если столкнётесь с какими-то проблемами, буду рад Вашим баг-репортам в issues. Также, если у Вас есть аккаунт — буду признателен за звёздочку :)
Спасибо, что дочитали до конца.
Комментарии (23)
qw1
24.04.2023 22:37В firefox не запустился, но информация полезная. Смотрим в консоли значение
window.mvcur.player.vars.url720p
, кликаем в ссылку, сохраняем файл.JustKappaMan Автор
24.04.2023 22:37Хм, оказывается в Firefox всё иначе. Неподписанные расширения просто не работают в релизной версии браузера. Честно говоря — не хочу заморачиваться с этим. ВК я в любом случае пользуюсь в Chrome.
Но если кто-то захочет собрать и подписать расширение под Firefox — пожалуйста. Лицензия позволяет. Можете даже в каталоге аддонов опубликовать.
AndreyAlin
24.04.2023 22:37Спасибо, что рассказали, скоро админы вк прикроют и эту лазейку.
JustKappaMan Автор
24.04.2023 22:37Да там в любом случае постоянно всё меняется. Ещё в феврале эти же переменные хранились в поле
mvPlayerVars
(или что-то подобное). Выпущу патч да и всё. Делов то.
NeoCode
24.04.2023 22:37А что плохого в скачивании видео, зачем прикрывать?
Я все равно скачиваю программой Internet Download Manager, она встраивается в браузеры и также имеет клиентскую десктопную часть. Но конечно чисто браузерное расширение удобнее.
JustKappaMan Автор
24.04.2023 22:37+1Ну как же. Люди не смотрят видео напрямую на платформе. Следовательно люди не смотрят рекламу. Следовательно метрики проседают. Хотя бы за этим :)
staffel
24.04.2023 22:37Было бы хорошо дать или инструкцию по установке, или выложить готовое для установки расширение с указанием для каких версий браузеров оно.
JustKappaMan Автор
24.04.2023 22:37Переходите в репозиторий на GitHub
Жмёте Code, распаковываете скачанный архив
В разделе расширений в браузере выбираете Загрузить распакованное / Load unpacked или что-то похожее и выбираете папку с расширением
Что касается поддержки браузеров и различных их версий: никакой экзотики в коде не используется, поэтому должно работать на большинстве относительно современных браузеров. Chromium-based и Firefox - уж точно.
Выше написали что эта версия на Firefox не работает, почти на 100% уверен что это связано с инъекцией. Сегодня починю. Выпущу патч.
staffel
24.04.2023 22:37+1С FF не устанавливается. Я скачал код, сжал в zip содержимое без главной папки, переименовал в xpi и "это дополнение не может быть установлено, т.к., по-видимому, оно повреждено".
qw1
24.04.2023 22:37+1На FF неподписанные расширения можно ставить только в версии браузера "Developer Edition". У меня и в Developer такая же ошибка.
JustKappaMan Автор
24.04.2023 22:37Хм, оказывается в Firefox всё иначе. Неподписанные расширения просто не работают в релизной версии браузера. Честно говоря — не хочу заморачиваться с этим. VK я в любом случае пользуюсь в Chrome.
Но если кто-то захочет собрать и подписать расширение под Firefox — пожалуйста. Лицензия позволяет. Можете даже в каталоге аддонов опубликовать.
P. S. Почему-то мне казалось что тестировал первую версию расширения в Firefox и тогда всё работало. Оказывается нет. Совсем заработался что-то. Нужно побольше спать.
qw1
24.04.2023 22:37Потому у комментатора выше и возник вопрос насчёт TamperMonkey. Функциональность юзер-скриптов примерно равна функциональности аддонов, после того, как Mozilla сломала старые мощные API, а заморочки с подписями не требуются.
rombell
24.04.2023 22:37Для vK есть и нормально работает vkOPT, что в виде плагина, что скриптом для TamperMonkey.
А вот такая же штука для дзена и рутуба была бы исключительно полезнаJustKappaMan Автор
24.04.2023 22:37На днях в свободное время гляну что там с Дзеном и Рутюбом. Может и реализую такую же штуку.
JustKappaMan Автор
24.04.2023 22:37+1@Kenya-West@staffel@qw1 добавил версию скрипта для Tampermonkey и расширил информацию в Readme. Всё уже в репозитории :)
grey_rat
24.04.2023 22:37Почему-то все создатели подобных расширений делают возможность "скачать" без "посмотреть". Почему не сразу оба?
Пример с ютубом и VLC плеером на смартфоне. Нажал, и видео сразу улетело в VLC плеер без закачки.
тоже самое и на компе https://m.youtube.com/watch?v=b-6MczEoa6I
Второй момент. Почему на каком-нибудь сайте после нажатия по ссылке вк или другого обязательно нужно переходить на медленную страницу вк? Неплохо придумано у savefromnet. Можно впереди ссылки дописать sfrom.net, с помощью расширения Redirector сделать это дописывание автоматически. И после нажатия по ссылке сразу получить готовый результат в виде облегчённой страницы с возможностью скачать или посмотреть
Везде приходится подстраиваться/допиливать самому.
JustKappaMan Автор
@Kenya-West@staffel@qw1 добавил версию скрипта для Tampermonkey и расширил информацию в Readme. Всё уже в репозитории :)