mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-12 11:01:45 +00:00
Merge branch 'master' into mix-fixes
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
#nav-bar-background, #header.ytmusic-item-section-renderer {
|
||||
background: rgba(0, 0, 0, 0.3) !important;
|
||||
backdrop-filter: blur(18px) !important;
|
||||
#nav-bar-background,
|
||||
#header.ytmusic-item-section-renderer,
|
||||
ytmusic-tabs {
|
||||
background: rgba(0, 0, 0, 0.3) !important;
|
||||
backdrop-filter: blur(8px) !important;
|
||||
}
|
||||
|
||||
#nav-bar-divider {
|
||||
display: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
module.exports = () => {
|
||||
document.addEventListener('apiLoaded', () => {
|
||||
document.querySelector('video').addEventListener('loadeddata', e => {
|
||||
e.target.pause();
|
||||
document.addEventListener('apiLoaded', apiEvent => {
|
||||
apiEvent.detail.addEventListener('videodatachange', name => {
|
||||
if (name === 'dataloaded') {
|
||||
apiEvent.detail.pauseVideo();
|
||||
document.querySelector('video').ontimeupdate = e => {
|
||||
e.target.pause();
|
||||
}
|
||||
} else {
|
||||
document.querySelector('video').ontimeupdate = null;
|
||||
}
|
||||
})
|
||||
}, { once: true, passive: true })
|
||||
};
|
||||
|
||||
@ -1,25 +1,23 @@
|
||||
const { existsSync, mkdirSync } = require("fs");
|
||||
const { join } = require("path");
|
||||
const { URL } = require("url");
|
||||
|
||||
const { dialog } = require("electron");
|
||||
const { dialog, ipcMain } = require("electron");
|
||||
const is = require("electron-is");
|
||||
const ytpl = require("ytpl");
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
const { setOptions } = require("../../config/plugins");
|
||||
const registerCallback = require("../../providers/song-info");
|
||||
const { sendError } = require("./back");
|
||||
const { defaultMenuDownloadLabel, getFolder } = require("./utils");
|
||||
|
||||
let downloadLabel = defaultMenuDownloadLabel;
|
||||
let metadataURL = undefined;
|
||||
let playingPlaylistId = undefined;
|
||||
let callbackIsRegistered = false;
|
||||
|
||||
module.exports = (win, options) => {
|
||||
if (!callbackIsRegistered) {
|
||||
registerCallback((info) => {
|
||||
metadataURL = info.url;
|
||||
ipcMain.on("video-src-changed", async (_, data) => {
|
||||
playingPlaylistId = JSON.parse(data)?.videoDetails?.playlistId;
|
||||
});
|
||||
callbackIsRegistered = true;
|
||||
}
|
||||
@ -28,17 +26,17 @@ module.exports = (win, options) => {
|
||||
{
|
||||
label: downloadLabel,
|
||||
click: async () => {
|
||||
const currentURL = metadataURL || win.webContents.getURL();
|
||||
const playlistID = new URL(currentURL).searchParams.get("list");
|
||||
if (!playlistID) {
|
||||
const currentPagePlaylistId = new URL(win.webContents.getURL()).searchParams.get("list");
|
||||
const playlistId = currentPagePlaylistId || playingPlaylistId;
|
||||
if (!playlistId) {
|
||||
sendError(win, new Error("No playlist ID found"));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`trying to get playlist ID: '${playlistID}'`);
|
||||
console.log(`trying to get playlist ID: '${playlistId}'`);
|
||||
let playlist;
|
||||
try {
|
||||
playlist = await ytpl(playlistID, {
|
||||
playlist = await ytpl(playlistId, {
|
||||
limit: options.playlistMaxItems || Infinity,
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
47
plugins/exponential-volume/front.js
Normal file
47
plugins/exponential-volume/front.js
Normal file
@ -0,0 +1,47 @@
|
||||
// "Youtube Music fix volume ratio 0.4" by Marco Pfeiffer
|
||||
// https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/
|
||||
|
||||
const exponentialVolume = () => {
|
||||
// manipulation exponent, higher value = lower volume
|
||||
// 3 is the value used by pulseaudio, which Barteks2x figured out this gist here: https://gist.github.com/Barteks2x/a4e189a36a10c159bb1644ffca21c02a
|
||||
// 0.05 (or 5%) is the lowest you can select in the UI which with an exponent of 3 becomes 0.000125 or 0.0125%
|
||||
const EXPONENT = 3;
|
||||
|
||||
const storedOriginalVolumes = new WeakMap();
|
||||
const { get, set } = Object.getOwnPropertyDescriptor(
|
||||
HTMLMediaElement.prototype,
|
||||
"volume"
|
||||
);
|
||||
Object.defineProperty(HTMLMediaElement.prototype, "volume", {
|
||||
get() {
|
||||
const lowVolume = get.call(this);
|
||||
const calculatedOriginalVolume = lowVolume ** (1 / EXPONENT);
|
||||
|
||||
// The calculated value has some accuracy issues which can lead to problems for implementations that expect exact values.
|
||||
// To avoid this, I'll store the unmodified volume to return it when read here.
|
||||
// This mostly solves the issue, but the initial read has no stored value and the volume can also change though external influences.
|
||||
// To avoid ill effects, I check if the stored volume is somewhere in the same range as the calculated volume.
|
||||
const storedOriginalVolume = storedOriginalVolumes.get(this);
|
||||
const storedDeviation = Math.abs(
|
||||
storedOriginalVolume - calculatedOriginalVolume
|
||||
);
|
||||
|
||||
const originalVolume =
|
||||
storedDeviation < 0.01
|
||||
? storedOriginalVolume
|
||||
: calculatedOriginalVolume;
|
||||
return originalVolume;
|
||||
},
|
||||
set(originalVolume) {
|
||||
const lowVolume = originalVolume ** EXPONENT;
|
||||
storedOriginalVolumes.set(this, originalVolume);
|
||||
set.call(this, lowVolume);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = () =>
|
||||
document.addEventListener("apiLoaded", exponentialVolume, {
|
||||
once: true,
|
||||
passive: true,
|
||||
});
|
||||
@ -4,10 +4,13 @@
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
/* fixes nav-bar-background opacity bug and allows clicking scrollbar through it */
|
||||
/* fixes nav-bar-background opacity bug, reposition it, and allows clicking scrollbar through it */
|
||||
#nav-bar-background {
|
||||
opacity: 1 !important;
|
||||
pointer-events: none;
|
||||
pointer-events: none !important;
|
||||
position: sticky !important;
|
||||
top: 0 !important;
|
||||
height: 75px !important;
|
||||
}
|
||||
|
||||
/* remove window dragging for nav bar (conflict with titlebar drag) */
|
||||
@ -17,9 +20,10 @@ ytmusic-pivot-bar-item-renderer {
|
||||
-webkit-app-region: unset !important;
|
||||
}
|
||||
|
||||
/* move up item selection renderer by 13 px */
|
||||
ytmusic-item-section-renderer.stuck #header.ytmusic-item-section-renderer {
|
||||
top: calc(var(--ytmusic-nav-bar-height) - 13px) !important;
|
||||
/* move up item selection renderers */
|
||||
ytmusic-item-section-renderer.stuck #header.ytmusic-item-section-renderer,
|
||||
ytmusic-tabs.stuck {
|
||||
top: calc(var(--ytmusic-nav-bar-height) - 15px) !important;
|
||||
}
|
||||
|
||||
/* fix weird positioning in search screen*/
|
||||
@ -28,8 +32,7 @@ ytmusic-header-renderer.ytmusic-search-page {
|
||||
}
|
||||
|
||||
/* Move navBar downwards */
|
||||
ytmusic-nav-bar[slot="nav-bar"],
|
||||
#nav-bar-background {
|
||||
ytmusic-nav-bar[slot="nav-bar"] {
|
||||
top: 17px !important;
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ const observePopupContainer = () => {
|
||||
|
||||
const observeVideo = () => {
|
||||
$('video').addEventListener('ratechange', forcePlaybackRate)
|
||||
$('video').addEventListener('loadeddata', forcePlaybackRate)
|
||||
$('video').addEventListener('srcChanged', forcePlaybackRate)
|
||||
}
|
||||
|
||||
const setupWheelListener = () => {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
const fetch = require("node-fetch");
|
||||
const is = require("electron-is");
|
||||
const { ipcMain } = require("electron");
|
||||
|
||||
const defaultConfig = require("../../config/defaults");
|
||||
const registerCallback = require("../../providers/song-info");
|
||||
const { sortSegments } = require("./segments");
|
||||
|
||||
let videoID;
|
||||
@ -13,15 +13,10 @@ module.exports = (win, options) => {
|
||||
...options,
|
||||
};
|
||||
|
||||
registerCallback(async (info) => {
|
||||
const newURL = info.url || win.webContents.getURL();
|
||||
const newVideoID = new URL(newURL).searchParams.get("v");
|
||||
|
||||
if (videoID !== newVideoID) {
|
||||
videoID = newVideoID;
|
||||
const segments = await fetchSegments(apiURL, categories);
|
||||
win.webContents.send("sponsorblock-skip", segments);
|
||||
}
|
||||
ipcMain.on("video-src-changed", async (_, data) => {
|
||||
videoID = JSON.parse(data)?.videoDetails?.videoId;
|
||||
const segments = await fetchSegments(apiURL, categories);
|
||||
win.webContents.send("sponsorblock-skip", segments);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ function $(selector) { return document.querySelector(selector); }
|
||||
|
||||
let options, player, video, api;
|
||||
|
||||
let api;
|
||||
|
||||
const switchButtonDiv = ElementFromFile(
|
||||
templatePath(__dirname, "button_template.html")
|
||||
);
|
||||
@ -40,8 +42,10 @@ function setup(e) {
|
||||
changeDisplay(e.target.checked);
|
||||
setOptions("video-toggle", options);
|
||||
})
|
||||
|
||||
video.addEventListener('srcChanged', videoStarted);
|
||||
|
||||
video.addEventListener('loadedmetadata', videoStarted);
|
||||
observeThumbnail();
|
||||
}
|
||||
|
||||
function changeDisplay(showVideo) {
|
||||
@ -57,10 +61,7 @@ function changeDisplay(showVideo) {
|
||||
function videoStarted() {
|
||||
if (player.videoMode_) {
|
||||
// switch to high res thumbnail
|
||||
const thumbnails = api.getPlayerResponse()?.videoDetails?.thumbnail?.thumbnails;
|
||||
if (thumbnails && thumbnails.length > 0) {
|
||||
$('#song-image img').src = thumbnails[thumbnails.length - 1].url;
|
||||
}
|
||||
forceThumbnail($('#song-image img'));
|
||||
// show toggle button
|
||||
switchButtonDiv.style.display = "initial";
|
||||
// change display to video mode if video exist & video is hidden & option.hideVideo = false
|
||||
@ -97,3 +98,22 @@ function moveVolumeHud(showVideo) {
|
||||
if (volumeHud)
|
||||
volumeHud.style.top = showVideo ? `${(player.clientHeight - video.clientHeight) / 2}px` : 0;
|
||||
}
|
||||
|
||||
function observeThumbnail() {
|
||||
const playbackModeObserver = new MutationObserver(mutations => {
|
||||
if (!$('#player').videoMode_) return;
|
||||
|
||||
mutations.forEach(mutation => {
|
||||
if (!mutation.target.src.startsWith('data:')) return;
|
||||
forceThumbnail(mutation.target)
|
||||
});
|
||||
});
|
||||
playbackModeObserver.observe($('#song-image img'), { attributeFilter: ["src"] })
|
||||
}
|
||||
|
||||
function forceThumbnail(img) {
|
||||
const thumbnails = $('#movie_player').getPlayerResponse()?.videoDetails?.thumbnail?.thumbnails;
|
||||
if (thumbnails && thumbnails.length > 0) {
|
||||
img.src = thumbnails[thumbnails.length - 1].url.split("?")[0];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user