Skip to content

Instantly share code, notes, and snippets.

@dEN5-tech
Created June 13, 2026 17:27
Show Gist options
  • Select an option

  • Save dEN5-tech/4dae13913dff8a66ac20583c6317ad51 to your computer and use it in GitHub Desktop.

Select an option

Save dEN5-tech/4dae13913dff8a66ac20583c6317ad51 to your computer and use it in GitHub Desktop.
mpv-lampa
(function () {
'use strict';
Lampa.Lang.add({
mpv_integration_title: {
ru: 'Интеграция MPV',
en: 'MPV Integration',
uk: 'Інтеграція MPV'
},
mpv_integration_descr: {
ru: 'Использовать внешний плеер MPV с поддержкой плейлистов M3U8',
en: 'Use external MPV player with M3U8 playlists support',
uk: 'Використовувати зовнішній плеєр MPV з підтримкою плейлистів M3U8'
},
mpv_integration_mode_title: {
ru: 'Режим MPV',
en: 'MPV Mode',
uk: 'Режим MPV'
},
mpv_integration_mode_descr: {
ru: 'Способ запуска плеера MPV',
en: 'How to launch the MPV player',
uk: 'Спосіб запуску плеєра MPV'
},
mpv_integration_enabled: {
ru: 'Включена',
en: 'Enabled',
uk: 'Увімкнена'
},
mpv_integration_disabled: {
ru: 'Выключена',
en: 'Disabled',
uk: 'Вимкнена'
},
mpv_noty_sent: {
ru: 'Плейлист отправлен в MPV',
en: 'Playlist sent to MPV',
uk: 'Плейлист відправлений в MPV'
},
mpv_noty_error: {
ru: 'Ошибка воспроизведения в MPV',
en: 'Playback error in MPV',
uk: 'Помилка відтворення в MPV'
},
mpv_noty_conn_error: {
ru: 'Не удалось связаться с сервером Lampac',
en: 'Failed to connect to Lampac server',
uk: 'Не вдалося зв\'язатися з сервером Lampac'
}
});
var Defined = {
localhost: '{localhost}'
};
function startPlugin() {
console.log('MPV Integration: Plugin initialized.');
// Monkey-patch Lampa.Player.play and Lampa.Player.playlist
var currentElement = null;
var originalPlay = Lampa.Player.play;
var originalPlaylist = Lampa.Player.playlist;
Lampa.Player.play = function (element) {
currentElement = element;
if (Lampa.Storage.get('mpv_integration_enabled', 'false') === 'true') {
setTimeout(function () {
if (currentElement) {
playInMpv(currentElement);
currentElement = null;
}
}, 50);
return;
}
originalPlay.apply(this, arguments);
};
Lampa.Player.playlist = function (playlist) {
if (Lampa.Storage.get('mpv_integration_enabled', 'false') === 'true') {
if (currentElement) {
currentElement.playlist = playlist;
}
return;
}
originalPlaylist.apply(this, arguments);
};
function playInMpv(element) {
var playlistItems = [];
var index = 0;
if (element.playlist && element.playlist.length > 0) {
playlistItems = element.playlist;
index = playlistItems.findIndex(function (item) {
return item.url === element.url || item.title === element.title;
});
if (index < 0) index = 0;
} else {
playlistItems = [element];
index = 0;
}
Lampa.Loading.start(function () {
Lampa.Loading.stop();
});
var payload = {
index: index,
playlist: playlistItems.map(function (item, i) {
return {
title: item.title || element.title || ('Episode ' + (i + 1)),
url: item.url
};
})
};
$.ajax({
url: Defined.localhost + '/player-inner/playlist',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(payload),
success: function (response) {
Lampa.Loading.stop();
if (response.success) {
var mode = Lampa.Storage.get('mpv_integration_mode', 'local');
if (mode === 'local') {
$.get(Defined.localhost + '/player-inner/play-playlist?id=' + response.id + '&index=' + response.index);
Lampa.Noty.show(Lampa.Lang.translate('mpv_noty_sent'));
} else if (mode === 'intent') {
var intentUrl = 'intent:' + encodeURIComponent(response.url) + '#Intent;package=is.xyz.mpv;type=video/*;end';
window.location.href = intentUrl;
} else if (mode === 'scheme') {
var schemeUrl = 'mpv://' + response.url;
window.location.href = schemeUrl;
}
} else {
Lampa.Noty.show(Lampa.Lang.translate('mpv_noty_error'));
}
},
error: function () {
Lampa.Loading.stop();
Lampa.Noty.show(Lampa.Lang.translate('mpv_noty_conn_error'));
}
});
}
// Add settings panel options
Lampa.Settings.listener.follow('open', function (e) {
if (e.name == 'player') {
var body = e.body;
if (!body.find('[data-parent="mpv_integration"]').length) {
var html = $('<div class="settings-param selector" data-parent="mpv_integration" data-type="select">\n' +
'<div class="settings-param__name">' + Lampa.Lang.translate('mpv_integration_title') + '</div>\n' +
'<div class="settings-param__value">Выключена</div>\n' +
'<div class="settings-param__descr">' + Lampa.Lang.translate('mpv_integration_descr') + '</div>\n' +
'</div>');
var val = Lampa.Storage.get('mpv_integration_enabled', 'false');
html.find('.settings-param__value').text(val === 'true' ? Lampa.Lang.translate('mpv_integration_enabled') : Lampa.Lang.translate('mpv_integration_disabled'));
html.on('hover:enter', function () {
var current = Lampa.Storage.get('mpv_integration_enabled', 'false');
var next = current === 'true' ? 'false' : 'true';
Lampa.Storage.set('mpv_integration_enabled', next);
html.find('.settings-param__value').text(next === 'true' ? Lampa.Lang.translate('mpv_integration_enabled') : Lampa.Lang.translate('mpv_integration_disabled'));
});
var modeHtml = $('<div class="settings-param selector" data-parent="mpv_integration_mode" data-type="select">\n' +
'<div class="settings-param__name">' + Lampa.Lang.translate('mpv_integration_mode_title') + '</div>\n' +
'<div class="settings-param__value">Локальный (Lampac)</div>\n' +
'<div class="settings-param__descr">' + Lampa.Lang.translate('mpv_integration_mode_descr') + '</div>\n' +
'</div>');
var mode = Lampa.Storage.get('mpv_integration_mode', 'local');
var modeNames = {
'local': { ru: 'Локальный (Lampac)', en: 'Local (Lampac)', uk: 'Локальний (Lampac)' },
'intent': { ru: 'Android Intent', en: 'Android Intent', uk: 'Android Intent' },
'scheme': { ru: 'Протокол (mpv://)', en: 'Protocol (mpv://)', uk: 'Протокол (mpv://)' }
};
var getModeName = function (m) {
var lang = Lampa.Storage.get('language', 'ru');
if (!modeNames[m]) m = 'local';
return modeNames[m][lang] || modeNames[m]['en'] || modeNames[m]['ru'];
};
modeHtml.find('.settings-param__value').text(getModeName(mode));
modeHtml.on('hover:enter', function () {
var currentMode = Lampa.Storage.get('mpv_integration_mode', 'local');
var modes = ['local', 'intent', 'scheme'];
var nextIndex = (modes.indexOf(currentMode) + 1) % modes.length;
var nextMode = modes[nextIndex];
Lampa.Storage.set('mpv_integration_mode', nextMode);
modeHtml.find('.settings-param__value').text(getModeName(nextMode));
});
body.append(html);
body.append(modeHtml);
Lampa.Controller.updateFormat(body);
}
}
});
}
if (window.appready) {
startPlugin();
} else {
Lampa.Listener.follow('app', function (e) {
if (e.type == 'ready') {
startPlugin();
}
});
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment