Press "tab" or "]" for Menu 1 , press "[" or "`" for Menu 2 + Auto Next Song
// ==UserScript==
// @name MUSIC CHILL
// @namespace http://tampermonkey.net/
// @version 6.6
// @description Press "tab" or "]" for Menu 1 , press "[" or "`" for Menu 2 + Auto Next Song
// @author XUAN & taochsgamedekiemgai2207 + Mood Audio + Effects + Custom EQ
// @match *://*/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const AudioConfig = {
defaultVolume: 85,
currentMood: 'studio',
reverb: 0.15,
stereoWiden: 1.3,
compressor: true,
limiter: true,
noiseGate: true
};
const MoodPresets = {
studio: {
name: '🎚️ Studio',
bass: 8,
mid: 3,
treble: 5,
reverb: 0.1,
stereo: 1.2,
desc: '✨ Âm thanh phòng thu chuyên nghiệp',
effect: 'Cân bằng hoàn hảo giữa các dải tần, âm thanh trung thực như trong phòng thu'
},
deep: {
name: '🌊 Deep',
bass: 12,
mid: 2,
treble: 3,
reverb: 0.2,
stereo: 1.3,
desc: '🎵 Âm trầm sâu lắng',
effect: 'Tăng cường bass, âm thanh ấm áp và sâu lắng, phù hợp nhạc ballad, chill'
},
bass: {
name: '🔊 Bass Boost',
bass: 15,
mid: 1,
treble: 4,
reverb: 0.15,
stereo: 1.4,
desc: '💥 Bass mạnh mẽ',
effect: 'Bass được đẩy lên tối đa, âm thanh sống động như trong club, phù hợp EDM, rap'
},
bright: {
name: '✨ Bright',
bass: 4,
mid: 4,
treble: 10,
reverb: 0.1,
stereo: 1.2,
desc: '🌟 Âm thanh sáng',
effect: 'Tăng treble, âm thanh trong trẻo và chi tiết, phù hợp nhạc acoustic, classical'
},
vocal: {
name: '🎤 Vocal',
bass: 5,
mid: 8,
treble: 6,
reverb: 0.12,
stereo: 1.1,
desc: '🎙️ Giọng hát rõ',
effect: 'Tập trung vào dải mid, giọng hát nổi bật và ấm áp, phù hợp bolero, tình ca'
},
chill: {
name: '😌 Chill',
bass: 6,
mid: 4,
treble: 4,
reverb: 0.25,
stereo: 1.4,
desc: '🍃 Thư giãn nhẹ nhàng',
effect: 'Âm thanh nhẹ nhàng, thoải mái, không gian rộng, phù hợp lofi, ambient'
},
cinematic: {
name: '🎬 Cinematic',
bass: 10,
mid: 5,
treble: 6,
reverb: 0.3,
stereo: 1.5,
desc: '🎥 Âm thanh điện ảnh',
effect: 'Không gian rộng lớn như rạp phim, âm thanh hoành tráng, phù hợp soundtrack'
},
night: {
name: '🌙 Night',
bass: 7,
mid: 3,
treble: 3,
reverb: 0.2,
stereo: 1.3,
desc: '🌃 Về đêm',
effect: 'Ấm áp và nhẹ nhàng, tạo cảm giác thư thái cho buổi tối'
},
morning: {
name: '☀️ Morning',
bass: 5,
mid: 5,
treble: 7,
reverb: 0.15,
stereo: 1.2,
desc: '🌅 Buổi sáng',
effect: 'Tươi sáng, trong trẻo, đánh thức mọi giác quan'
},
energy: {
name: '⚡ Energy',
bass: 9,
mid: 6,
treble: 8,
reverb: 0.1,
stereo: 1.3,
desc: '🔥 Sôi động',
effect: 'Năng lượng tràn đầy, âm thanh mạnh mẽ, phù hợp gym, thể thao'
},
jazz: {
name: '🎷 Jazz',
bass: 6,
mid: 6,
treble: 5,
reverb: 0.2,
stereo: 1.3,
desc: '🎺 Jazz club',
effect: 'Ấm áp như trong quán jazz, tiếng kèn và bass mềm mại'
},
acoustic: {
name: '🎸 Acoustic',
bass: 4,
mid: 7,
treble: 6,
reverb: 0.18,
stereo: 1.2,
desc: '🎵 Âm thanh mộc',
effect: 'Tự nhiên như đang nghe nhạc sống, phù hợp guitar, piano'
},
bluetooth: {
name: '📱 Bluetooth',
bass: 10,
mid: 4,
treble: 6,
reverb: 0.12,
stereo: 1.1,
desc: '🎧 Tối ưu loa Bluetooth',
effect: 'Tối ưu cho loa Bluetooth, bass mạnh mà không bị rè'
},
headphone: {
name: '🎧 Headphone',
bass: 7,
mid: 5,
treble: 6,
reverb: 0.1,
stereo: 1.3,
desc: '🎧 Tai nghe',
effect: 'Tối ưu cho tai nghe, âm trường rộng và chi tiết'
},
classical: {
name: '🎻 Classical',
bass: 5,
mid: 6,
treble: 7,
reverb: 0.25,
stereo: 1.4,
desc: '🎼 Nhạc cổ điển',
effect: 'Không gian rộng, dàn nhạc giao hưởng sống động'
},
rock: {
name: '🤘 Rock',
bass: 11,
mid: 5,
treble: 7,
reverb: 0.15,
stereo: 1.3,
desc: '🎸 Rock mạnh mẽ',
effect: 'Guitar điện và trống mạnh mẽ, phù hợp rock, metal'
},
smallSpeaker: {
name: '📢 Small Speaker',
bass: 8,
mid: 6,
treble: 8,
reverb: 0.08,
stereo: 1.1,
desc: '📱 Loa nhỏ',
effect: 'Tối ưu cho loa điện thoại, laptop, âm thanh rõ ràng'
},
clear: {
name: '💎 Clear',
bass: 5,
mid: 5,
treble: 5,
reverb: 0.05,
stereo: 1.1,
desc: '✨ Trong trẻo',
effect: 'Âm thanh tự nhiên nhất, không màu mè, nghe như tác giả muốn'
},
threeD: {
name: '🌀 3D Surround',
bass: 8,
mid: 4,
treble: 6,
reverb: 0.3,
stereo: 1.8,
desc: '🎯 Âm thanh vòm',
effect: 'Âm thanh vòm 3D, không gian bao quanh, sống động'
}
};
// ==================== AUDIO ENGINE ====================
class StudioAudioEngine {
constructor() {
this.context = null;
this.nodes = {};
this.isActive = false;
this.videoElement = null;
this.currentMood = 'studio';
}
async init() {
try {
this.context = new (window.AudioContext || window.webkitAudioContext)({
latencyHint: 'interactive',
sampleRate: 48000
});
this.createAudioNodes();
if (this.context.state === 'suspended') {
await this.context.resume();
}
this.isActive = true;
console.log('🎧 Studio Audio Engine ready');
} catch (e) {
console.log('Audio engine not available');
}
}
createAudioNodes() {
this.nodes.compressor = this.context.createDynamicsCompressor();
this.nodes.compressor.threshold.value = -24;
this.nodes.compressor.knee.value = 30;
this.nodes.compressor.ratio.value = 12;
this.nodes.compressor.attack.value = 0.003;
this.nodes.compressor.release.value = 0.25;
this.nodes.bassEQ = this.context.createBiquadFilter();
this.nodes.bassEQ.type = 'lowshelf';
this.nodes.bassEQ.frequency.value = 150;
this.nodes.midEQ = this.context.createBiquadFilter();
this.nodes.midEQ.type = 'peaking';
this.nodes.midEQ.frequency.value = 1000;
this.nodes.midEQ.Q.value = 1;
this.nodes.trebleEQ = this.context.createBiquadFilter();
this.nodes.trebleEQ.type = 'highshelf';
this.nodes.trebleEQ.frequency.value = 4000;
this.nodes.reverb = this.context.createConvolver();
this.createReverb();
this.nodes.merger = this.context.createChannelMerger(2);
this.nodes.splitter = this.context.createChannelSplitter(2);
this.nodes.gainL = this.context.createGain();
this.nodes.gainR = this.context.createGain();
this.nodes.limiter = this.context.createDynamicsCompressor();
this.nodes.limiter.threshold.value = -6;
this.nodes.limiter.knee.value = 0;
this.nodes.limiter.ratio.value = 20;
this.nodes.limiter.attack.value = 0.001;
this.nodes.limiter.release.value = 0.01;
this.nodes.masterGain = this.context.createGain();
this.nodes.masterGain.gain.value = AudioConfig.defaultVolume / 100 * 1.2;
this.applyMood(AudioConfig.currentMood);
}
createReverb() {
try {
const duration = 1.5;
const decay = 2;
const sampleRate = this.context.sampleRate;
const length = sampleRate * duration;
const impulse = this.context.createBuffer(2, length, sampleRate);
for (let channel = 0; channel < 2; channel++) {
const channelData = impulse.getChannelData(channel);
for (let i = 0; i < length; i++) {
channelData[i] = (Math.random() * 2 - 1) *
Math.pow(1 - i / length, decay);
}
}
this.nodes.reverb.buffer = impulse;
} catch (e) {
console.log('Reverb creation failed');
}
}
showMoodEffect(moodId) {
const mood = MoodPresets[moodId];
if (!mood) return;
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px 30px;
border-radius: 15px;
z-index: 1000000;
font-family: Arial, sans-serif;
box-shadow: 0 10px 40px rgba(0,0,0,0.25);
animation: moodPopIn 0.5s ease-out;
text-align: center;
max-width: 300px;
border: 2px solid rgba(255,255,255,0.2);
`;
notification.innerHTML = `
<div style="font-size: 40px; margin-bottom: 10px;">${mood.name.split(' ')[0]}</div>
<div style="font-size: 18px; font-weight: bold; margin-bottom: 5px;">${mood.desc}</div>
<div style="font-size: 14px; opacity: 0.9; margin-bottom: 15px;">${mood.effect}</div>
<div style="display: flex; gap: 10px; justify-content: center;">
<div style="background: rgba(255,255,255,0.2); padding: 5px 10px; border-radius: 20px;">
Bass: ${mood.bass}dB
</div>
<div style="background: rgba(255,255,255,0.2); padding: 5px 10px; border-radius: 20px;">
Treble: ${mood.treble}dB
</div>
</div>
<div style="margin-top: 10px; font-size: 12px; opacity: 0.7;">⚡ Đã kích hoạt</div>
`;
const style = document.createElement('style');
style.textContent = `
@keyframes moodPopIn {
0% { transform: translate(-50%, -30%) scale(0.8); opacity: 0; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
@keyframes moodPopOut {
0% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
100% { transform: translate(-50%, -70%) scale(0.8); opacity: 0; }
}
`;
document.head.appendChild(style);
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'moodPopOut 0.3s ease-in forwards';
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 300);
}, 3000);
this.showEQVisualizer(mood);
}
showEQVisualizer(mood) {
const visualizer = document.createElement('div');
visualizer.style.cssText = `
position: fixed;
bottom: 30px;
right: 30px;
background: rgba(0,0,0,0.25);
color: white;
padding: 15px;
border-radius: 10px;
z-index: 999999;
font-family: Arial, sans-serif;
backdrop-filter: blur(5px);
border: 1px solid #4CAF50;
animation: slideInRight 0.3s ease-out;
`;
const bars = ['Bass', 'Mid', 'Treble'];
const values = [mood.bass, mood.mid, mood.treble];
const maxValue = 15;
let barsHtml = '<div style="margin-bottom: 10px; color: #4CAF50;">🎚️ EQ Visualizer</div>';
bars.forEach((bar, index) => {
const percentage = (values[index] / maxValue) * 100;
barsHtml += `
<div style="margin-bottom: 8px;">
<div style="display: flex; justify-content: space-between; margin-bottom: 3px;">
<span>${bar}</span>
<span>${values[index]}dB</span>
</div>
<div style="width: 200px; height: 20px; background: #333; border-radius: 10px; overflow: hidden;">
<div style="width: ${percentage}%; height: 100%; background: linear-gradient(90deg, #4CAF50, #8BC34A); border-radius: 10px;"></div>
</div>
</div>
`;
});
barsHtml += `
<div style="margin-top: 10px; display: flex; gap: 10px; color: #aaa; font-size: 11px;">
<span>🌊 Reverb: ${Math.round(mood.reverb * 100)}%</span>
<span>🎯 Stereo: ${mood.stereo}x</span>
</div>
`;
visualizer.innerHTML = barsHtml;
const style = document.createElement('style');
style.textContent = `
@keyframes slideInRight {
from { transform: translateX(100px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
document.body.appendChild(visualizer);
setTimeout(() => {
if (visualizer.parentNode) {
visualizer.style.animation = 'slideInRight 0.3s ease-out reverse';
setTimeout(() => visualizer.remove(), 300);
}
}, 5000);
}
applyMood(moodId) {
if (!this.isActive || !this.nodes.bassEQ) return;
const mood = MoodPresets[moodId] || MoodPresets.studio;
this.currentMood = moodId;
this.nodes.bassEQ.gain.value = mood.bass;
this.nodes.midEQ.gain.value = mood.mid;
this.nodes.trebleEQ.gain.value = mood.treble;
AudioConfig.reverb = mood.reverb;
AudioConfig.stereoWiden = mood.stereo;
console.log(`🎵 Applied mood: ${mood.name}`);
const moodDisplay = document.getElementById('currentMood');
if (moodDisplay) {
moodDisplay.innerHTML = `${mood.name} <span style="color:#aaa; font-size:10px;">(${mood.desc})</span>`;
}
if (window.bassSlider) window.bassSlider.value = mood.bass;
if (window.midSlider) window.midSlider.value = mood.mid;
if (window.trebleSlider) window.trebleSlider.value = mood.treble;
if (window.reverbSlider) window.reverbSlider.value = Math.round(mood.reverb * 100);
if (window.stereoSlider) window.stereoSlider.value = mood.stereo;
this.showMoodEffect(moodId);
}
// ==================== THÊM: RECONNECT ĐỂ CẬP NHẬT REVERB + STEREO (CHO CUSTOM) ====================
reconnectToVideo() {
if (!this.videoElement || !this.isActive) {
console.log('⚠️ Không có video để reconnect');
return;
}
try {
this.connectToVideo(this.videoElement);
console.log('🎧 Audio chain đã reconnect với thiết lập mới (Reverb + Stereo)');
} catch (e) {
console.log('Reconnect failed:', e);
}
}
connectToVideo(videoElement) {
if (!this.isActive || !this.context || !videoElement) return false;
try {
this.videoElement = videoElement;
if (this.nodes.source) {
this.nodes.source.disconnect();
}
this.nodes.source = this.context.createMediaElementSource(videoElement);
let currentNode = this.nodes.source;
currentNode.connect(this.nodes.bassEQ);
currentNode = this.nodes.bassEQ;
currentNode.connect(this.nodes.midEQ);
currentNode = this.nodes.midEQ;
currentNode.connect(this.nodes.trebleEQ);
currentNode = this.nodes.trebleEQ;
currentNode.connect(this.nodes.compressor);
currentNode = this.nodes.compressor;
// SỬ DỤNG AudioConfig thay vì mood (để custom hoạt động)
const stereo = AudioConfig.stereoWiden;
const reverbLevel = AudioConfig.reverb;
if (stereo > 1) {
currentNode.connect(this.nodes.splitter);
this.nodes.splitter.connect(this.nodes.gainL, 0);
this.nodes.splitter.connect(this.nodes.gainR, 1);
this.nodes.gainL.gain.value = 1;
this.nodes.gainR.gain.value = 1;
this.nodes.gainL.connect(this.nodes.merger, 0, 0);
this.nodes.gainR.connect(this.nodes.merger, 0, 1);
currentNode = this.nodes.merger;
}
if (reverbLevel > 0.05) {
const dryGain = this.context.createGain();
const wetGain = this.context.createGain();
dryGain.gain.value = 1 - reverbLevel;
wetGain.gain.value = reverbLevel;
currentNode.connect(dryGain);
currentNode.connect(this.nodes.reverb);
this.nodes.reverb.connect(wetGain);
dryGain.connect(this.nodes.limiter);
wetGain.connect(this.nodes.limiter);
} else {
currentNode.connect(this.nodes.limiter);
}
this.nodes.limiter.connect(this.nodes.masterGain);
this.nodes.masterGain.connect(this.context.destination);
console.log(`🎵 Studio audio active - Mood: ${MoodPresets[this.currentMood].name} | Reverb: ${reverbLevel} | Stereo: ${stereo}`);
return true;
} catch (e) {
console.log('Could not connect audio processor:', e);
return false;
}
}
setVolume(vol) {
if (this.nodes.masterGain) {
this.nodes.masterGain.gain.value = (vol / 100) * 1.2;
}
}
}
const audioEngine = new StudioAudioEngine();
// === BIẾN GLOBAL CHO CUSTOM SLIDERS (để sync khi đổi mood) ===
let bassSlider, midSlider, trebleSlider, reverbSlider, stereoSlider;
// Create the music menu container
const musicMenuContainer = document.createElement('div');
musicMenuContainer.id = 'musicMenuContainer';
musicMenuContainer.style.position = 'absolute';
musicMenuContainer.style.top = '0';
musicMenuContainer.style.left = '0';
musicMenuContainer.style.width = '280px';
musicMenuContainer.style.maxHeight = '100vh';
musicMenuContainer.style.overflowY = 'auto';
musicMenuContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.1)';
musicMenuContainer.style.color = '#fff';
musicMenuContainer.style.borderRadius = '10px';
musicMenuContainer.style.padding = '20px';
musicMenuContainer.style.zIndex = '9999';
musicMenuContainer.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.25)';
musicMenuContainer.style.display = 'none';
// Title
const musicTitle = document.createElement('h2');
musicTitle.textContent = ' bấm "tab" hoặc "]" để mở/tắt menu , bấm "[" hoặc "`" để mở menu số 2';
musicTitle.style.textAlign = 'center';
musicTitle.style.fontSize = '14px';
musicMenuContainer.appendChild(musicTitle);
// ==================== PHẦN ĐỀ NGHỊ BÀI HÁT THEO THỜI GIAN ====================
const suggestionContainer = document.createElement('div');
suggestionContainer.style.marginBottom = '15px';
suggestionContainer.style.padding = '12px';
suggestionContainer.style.backgroundColor = 'rgba(255, 193, 7, 0.15)';
suggestionContainer.style.borderRadius = '16px';
suggestionContainer.style.border = '1px solid rgba(255, 193, 7, 0.25)';
suggestionContainer.style.backdropFilter = 'blur(8px)';
suggestionContainer.style.textAlign = 'center';
const clockDiv = document.createElement('div');
clockDiv.style.fontSize = '28px';
clockDiv.style.fontWeight = 'bold';
clockDiv.style.fontFamily = 'monospace';
clockDiv.style.letterSpacing = '2px';
clockDiv.style.textShadow = '0 0 10px rgba(255,193,7,0.25)';
clockDiv.style.marginBottom = '10px';
const suggestedSongDiv = document.createElement('div');
suggestedSongDiv.style.fontSize = '14px';
suggestedSongDiv.style.marginBottom = '10px';
suggestedSongDiv.style.padding = '8px';
suggestedSongDiv.style.backgroundColor = 'rgba(0,0,0,0.25)';
suggestedSongDiv.style.borderRadius = '20px';
suggestedSongDiv.style.wordBreak = 'break-word';
const playSuggestBtn = document.createElement('button');
playSuggestBtn.textContent = '🎵 Phát ngay';
playSuggestBtn.style.backgroundColor = 'rgba(255, 193, 7, 0.25)';
playSuggestBtn.style.border = '1px solid rgba(255, 193, 7, 0.25)';
playSuggestBtn.style.marginTop = '5px';
playSuggestBtn.style.padding = '8px';
playSuggestBtn.style.fontSize = '12px';
playSuggestBtn.style.borderRadius = '30px';
playSuggestBtn.style.cursor = 'pointer';
playSuggestBtn.style.transition = 'all 0.2s';
playSuggestBtn.addEventListener('mouseover', () => {
playSuggestBtn.style.backgroundColor = 'rgba(255, 193, 7, 0.25)';
playSuggestBtn.style.transform = 'scale(1.02)';
});
playSuggestBtn.addEventListener('mouseout', () => {
playSuggestBtn.style.backgroundColor = 'rgba(255, 193, 7, 0.25)';
playSuggestBtn.style.transform = 'scale(1)';
});
suggestionContainer.appendChild(clockDiv);
suggestionContainer.appendChild(suggestedSongDiv);
suggestionContainer.appendChild(playSuggestBtn);
musicMenuContainer.appendChild(suggestionContainer);
// ==================== MOOD SELECTOR ====================
const moodContainer = document.createElement('div');
moodContainer.style.marginBottom = '15px';
moodContainer.style.padding = '10px';
moodContainer.style.backgroundColor = 'rgba(76, 175, 80, 0.2)';
moodContainer.style.borderRadius = '8px';
moodContainer.style.border = '1px solid #4CAF50';
const moodTitle = document.createElement('div');
moodTitle.textContent = '🎵 TÂM TRẠNG ÂM THANH';
moodTitle.style.fontWeight = 'bold';
moodTitle.style.marginBottom = '10px';
moodTitle.style.color = '#4CAF50';
moodTitle.style.textAlign = 'center';
moodContainer.appendChild(moodTitle);
const currentMoodDisplay = document.createElement('div');
currentMoodDisplay.id = 'currentMood';
currentMoodDisplay.style.marginBottom = '10px';
currentMoodDisplay.style.padding = '5px';
currentMoodDisplay.style.backgroundColor = 'rgba(255,255,255,0.1)';
currentMoodDisplay.style.borderRadius = '5px';
currentMoodDisplay.style.textAlign = 'center';
currentMoodDisplay.style.fontSize = '12px';
currentMoodDisplay.innerHTML = '🎚️ Studio <span style="color:#aaa; font-size:10px;">(✨ Âm thanh phòng thu chuyên nghiệp)</span>';
moodContainer.appendChild(currentMoodDisplay);
// Grid mood buttons
const moodGrid = document.createElement('div');
moodGrid.style.display = 'grid';
moodGrid.style.gridTemplateColumns = 'repeat(2, 1fr)';
moodGrid.style.gap = '5px';
const moodIds = ['studio', 'deep', 'bass', 'bright', 'vocal', 'chill', 'cinematic', 'night', 'morning', 'energy', 'jazz', 'acoustic', 'bluetooth', 'headphone', 'classical', 'rock', 'smallSpeaker', 'clear', 'threeD'];
moodIds.forEach(moodId => {
const mood = MoodPresets[moodId];
const btn = document.createElement('button');
btn.textContent = mood.name;
btn.title = mood.desc; // Hiện tooltip khi hover
btn.style.padding = '8px 4px';
btn.style.backgroundColor = moodId === 'studio' ? '#4CAF50' : 'rgba(33, 150, 243, 0.25)';
btn.style.color = 'white';
btn.style.border = 'none';
btn.style.borderRadius = '5px';
btn.style.cursor = 'pointer';
btn.style.fontSize = '11px';
btn.style.transition = 'all 0.2s';
btn.style.whiteSpace = 'nowrap';
btn.style.overflow = 'hidden';
btn.style.textOverflow = 'ellipsis';
btn.onmouseover = () => {
btn.style.backgroundColor = moodId === 'studio' ? '#45a049' : '#2196F3';
btn.style.transform = 'scale(1.02)';
};
btn.onmouseout = () => {
btn.style.backgroundColor = moodId === 'studio' ? '#4CAF50' : 'rgba(33, 150, 243, 0.25)';
btn.style.transform = 'scale(1)';
};
btn.onclick = () => {
audioEngine.applyMood(moodId);
moodGrid.querySelectorAll('button').forEach(b => {
b.style.backgroundColor = 'rgba(33, 150, 243, 0.25)';
});
btn.style.backgroundColor = '#4CAF50';
};
moodGrid.appendChild(btn);
});
moodContainer.appendChild(moodGrid);
musicMenuContainer.appendChild(moodContainer);
// ==================== THÊM: PHẦN TÙY CHỈNH EQ (ĐỘ TRẦM - CAO VÚT - NHẸ NHÀNG) ====================
const customContainer = document.createElement('div');
customContainer.style.marginTop = '15px';
customContainer.style.padding = '12px';
customContainer.style.backgroundColor = 'rgba(33, 150, 243, 0.25)';
customContainer.style.borderRadius = '8px';
customContainer.style.border = '1px solid #2196F3';
const customTitle = document.createElement('div');
customTitle.textContent = '🎛️ TÙY CHỈNH EQ (theo ý bạn)';
customTitle.style.fontWeight = 'bold';
customTitle.style.marginBottom = '12px';
customTitle.style.color = '#2196F3';
customTitle.style.textAlign = 'center';
customContainer.appendChild(customTitle);
// Bass (Độ trầm)
const bassLabel = document.createElement('label');
bassLabel.textContent = 'Độ trầm (Bass dB):';
bassLabel.style.display = 'block';
bassLabel.style.marginBottom = '4px';
bassLabel.style.fontSize = '13px';
customContainer.appendChild(bassLabel);
bassSlider = createSlider(-15, 15, 8);
bassSlider.style.marginBottom = '8px';
bassSlider.addEventListener('input', () => {
if (audioEngine.isActive && audioEngine.nodes.bassEQ) {
audioEngine.nodes.bassEQ.gain.value = parseFloat(bassSlider.value);
}
});
customContainer.appendChild(bassSlider);
// Mid
const midLabel = document.createElement('label');
midLabel.textContent = 'Độ trung (Mid dB):';
midLabel.style.display = 'block';
midLabel.style.marginBottom = '4px';
midLabel.style.fontSize = '13px';
customContainer.appendChild(midLabel);
midSlider = createSlider(-12, 12, 3);
midSlider.style.marginBottom = '8px';
midSlider.addEventListener('input', () => {
if (audioEngine.isActive && audioEngine.nodes.midEQ) {
audioEngine.nodes.midEQ.gain.value = parseFloat(midSlider.value);
}
});
customContainer.appendChild(midSlider);
// Treble (Độ cao vút)
const trebleLabel = document.createElement('label');
trebleLabel.textContent = 'Độ cao vút (Treble dB):';
trebleLabel.style.display = 'block';
trebleLabel.style.marginBottom = '4px';
trebleLabel.style.fontSize = '13px';
customContainer.appendChild(trebleLabel);
trebleSlider = createSlider(-12, 15, 5);
trebleSlider.style.marginBottom = '8px';
trebleSlider.addEventListener('input', () => {
if (audioEngine.isActive && audioEngine.nodes.trebleEQ) {
audioEngine.nodes.trebleEQ.gain.value = parseFloat(trebleSlider.value);
}
});
customContainer.appendChild(trebleSlider);
// Reverb (Nhẹ nhàng - Độ vang)
const reverbLabel = document.createElement('label');
reverbLabel.textContent = 'Độ vang / Nhẹ nhàng (Reverb %):';
reverbLabel.style.display = 'block';
reverbLabel.style.marginBottom = '4px';
reverbLabel.style.fontSize = '13px';
customContainer.appendChild(reverbLabel);
reverbSlider = createSlider(0, 50, 15);
reverbSlider.style.marginBottom = '8px';
reverbSlider.addEventListener('input', () => {
AudioConfig.reverb = parseFloat(reverbSlider.value) / 100;
});
customContainer.appendChild(reverbSlider);
// Stereo
const stereoLabel = document.createElement('label');
stereoLabel.textContent = 'Độ rộng âm trường (Stereo x):';
stereoLabel.style.display = 'block';
stereoLabel.style.marginBottom = '4px';
stereoLabel.style.fontSize = '13px';
customContainer.appendChild(stereoLabel);
stereoSlider = createSlider(1, 2, 1.3);
stereoSlider.step = '0.1';
stereoSlider.style.marginBottom = '10px';
stereoSlider.addEventListener('input', () => {
AudioConfig.stereoWiden = parseFloat(stereoSlider.value);
});
customContainer.appendChild(stereoSlider);
// Nút reconnect (vì Reverb + Stereo cần rebuild chain)
const reconnectBtn = createButton('🔄 Cập nhật Reverb & Stereo', 'rgba(255, 140, 0, 0.25)');
reconnectBtn.style.marginTop = '5px';
reconnectBtn.addEventListener('click', () => {
audioEngine.reconnectToVideo();
});
customContainer.appendChild(reconnectBtn);
// Thêm custom vào menu
musicMenuContainer.appendChild(customContainer);
// Volume control
const volumeLabel = document.createElement('label');
volumeLabel.textContent = 'âm thanh:';
musicMenuContainer.appendChild(volumeLabel);
const volumeSlider = createSlider(0, 100, 85);
volumeSlider.addEventListener('input', () => {
const volume = volumeSlider.value;
if (player) {
player.setVolume(volume);
}
audioEngine.setVolume(volume);
});
musicMenuContainer.appendChild(volumeSlider);
// Mute/Unmute button
const muteButton = createButton('tắt tiếng', 'rgba(255, 165, 0, 0.25)');
let isMuted = false;
muteButton.addEventListener('click', () => {
isMuted = !isMuted;
if (player) {
player.setVolume(isMuted ? 0 : volumeSlider.value);
}
audioEngine.setVolume(isMuted ? 0 : volumeSlider.value);
muteButton.textContent = isMuted ? 'mở tiếng' : 'tắt tiếng';
});
musicMenuContainer.appendChild(muteButton);
// Playback speed control
const speedLabel = document.createElement('label');
speedLabel.textContent = 'tốc độ nhạc:';
musicMenuContainer.appendChild(speedLabel);
const speedSelect = createSelect([0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9, 2,3,4,5,6,7,8,9,10,100,1000,1000000,1000000], 'x');
speedSelect.addEventListener('change', () => {
player.setPlaybackRate(parseFloat(speedSelect.value));
});
musicMenuContainer.appendChild(speedSelect);
// Track progress bar
const progressContainer = document.createElement('div');
const progressBar = document.createElement('input');
progressBar.type = 'range';
progressBar.min = '0';
progressBar.max = '100';
progressBar.value = '0';
progressBar.style.width = '100%';
progressBar.style.marginBottom = '10px';
progressBar.disabled = true;
progressBar.addEventListener('input', () => {
const time = (progressBar.value / 100) * player.getDuration();
player.seekTo(time);
});
progressContainer.appendChild(progressBar);
musicMenuContainer.appendChild(progressContainer);
// Song duration display
const durationDisplay = document.createElement('div');
durationDisplay.textContent = 'thời gian: 0:00 / 0:00';
durationDisplay.style.textAlign = 'center';
musicMenuContainer.appendChild(durationDisplay);
// ==================== THÊM BIẾN CHO LOOP VÀ AUTO NEXT ====================
let loopMode = 'none';
let sequentialMode = false; // Chế độ tự động chuyển bài tiếp theo
let currentMusic = null;
let currentMusicIndex = -1; // Vị trí bài hiện tại trong musicList
let musicButtons = []; // Mảng lưu các button tương ứng với từng bài
// ==================== THÊM NÚT LOOP ====================
const loopButton = createButton('➡️ Không lặp', 'rgba(128, 128, 128,0.25)');
loopButton.addEventListener('click', () => {
if (loopMode === 'none') {
loopMode = 'single';
loopButton.textContent = '🔂 Lặp bài này';
loopButton.style.backgroundColor = 'rgba(76, 175, 80,0.25)';
} else {
loopMode = 'none';
loopButton.textContent = '➡️ Không lặp';
loopButton.style.backgroundColor = 'rgba(128, 128, 128,0.25)';
}
});
musicMenuContainer.appendChild(loopButton);
// ==================== THÊM NÚT AUTO NEXT (CHUYỂN BÀI TIẾP THEO) ====================
const sequentialButton = createButton('⏭️ Auto next: OFF', 'rgba(0, 150, 255,0.25)');
sequentialButton.addEventListener('click', () => {
sequentialMode = !sequentialMode;
sequentialButton.textContent = sequentialMode ? '⏭️ Auto next: ON' : '⏭️ Auto next: OFF';
sequentialButton.style.backgroundColor = sequentialMode ? 'rgba(0, 200, 100,0.35)' : 'rgba(0, 150, 255,0.25)';
});
musicMenuContainer.appendChild(sequentialButton);
// ==================== CÁC NÚT ĐIỀU KHIỂN (TẠM DỪNG, NGẪU NHIÊN, DỪNG) ====================
// Create Pause/Play Button
const pauseButton = createButton('TẠM DỪNG', 'rgba(0, 255, 0,0.25)');
pauseButton.addEventListener('click', () => {
if (currentPlayingID) {
const state = player.getPlayerState();
if (state === YT.PlayerState.PLAYING) {
player.pauseVideo();
pauseButton.textContent = 'BẮT ĐẦU ';
} else {
player.playVideo();
pauseButton.textContent = 'TẠM DỪNG';
}
}
});
musicMenuContainer.appendChild(pauseButton);
// Create Random Play Button
const randomPlayButton = createButton('ngẫu nhiên BÀI NHẠC', 'rgba(255, 0, 255, 0.25)');
randomPlayButton.addEventListener('click', () => {
const randomIndex = Math.floor(Math.random() * musicList.length);
const randomMusic = musicList[randomIndex];
const targetButton = musicButtons[randomIndex] || null;
playMusic(randomMusic, targetButton);
});
musicMenuContainer.appendChild(randomPlayButton);
// Create Stop Music button
const stopButton = createButton('Dừng nhạc', 'rgba(255, 0, 0, 0.25)');
stopButton.addEventListener('click', () => {
if (currentPlayingID) {
player.stopVideo();
currentPlayingID = null;
if (currentButton) {
currentButton.textContent = currentButton.textContent.replace(' (Chill nào)', ' (nghe thử xem)');
currentButton.style.color = '#fff';
}
}
});
musicMenuContainer.appendChild(stopButton);
// List of music genres and their YouTube links
const musicList = [
{ name: 'Địa Ngục Trần Gian (Thazh x Đông Remix)', url: 'https://www.youtube.com/watch?v=05S2uf37ufc' },
{ name: 'The Right Path', url: 'https://www.youtube.com/watch?v=o_Figo57l8s&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=114&ab_channel=KainRecordings' },
{ name: 'Glass Animals', url: 'https://www.youtube.com/watch?v=6APgzehjAQM&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=113' },
{ name: 'Lucky x Go Girl', url: 'https://www.youtube.com/watch?v=cnbUjIhuryc' },
{ name: 'chill 1', url: 'https://www.youtube.com/watch?v=AQbvCfRCFvg&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=111&pp=gAQBiAQB8AUB' },
{ name: 'Darkside', url: 'https://www.youtube.com/watch?v=AIikYWUbAB0&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=110' },
{ name: 'lovely', url: 'https://www.youtube.com/watch?v=0Ghcjygr66g&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=106' },
{ name: 'chill 2', url: 'https://www.youtube.com/watch?v=5yaTVGSXAMc&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=103' },
{ name: 'chill 3', url: 'https://www.youtube.com/watch?v=Y6AiKryrDyk&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=104&pp=gAQBiAQB8AUB' },
{ name: 'I Want You to Know', url: 'https://www.youtube.com/watch?v=iwPEPqNerPY&ab_channel=BeatPanda' },
{ name: 'Tháng Năm Không Quên', url: 'https://www.youtube.com/watch?v=g3s-OdZazbQ&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=102' },
{ name: 'Bài Hát Liên Quân', url: 'https://www.youtube.com/watch?v=CxXN5DmI9s4&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=101' },
{ name: 'DDTank - Tết Nhà Bà Hoan Parody ', url: 'https://www.youtube.com/watch?v=NRRs9HyfNMc&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=95' },
{ name: 'Legendary', url: 'https://www.youtube.com/watch?v=cTlshvPrIZo&list=RDQMBlegB1oalTw&index=19' },
{ name: 'ĐẾ VƯƠNG', url: 'https://www.youtube.com/watch?v=qkPgUgkQE4Y&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=93' },
{ name: 'Lost Sky', url: 'https://www.youtube.com/watch?v=L7kF4MXXCoA&list=RDQMBlegB1oalTw&index=21' },
{ name: 'Tướng Quân ', url: 'https://www.youtube.com/watch?v=U-hAhjg56HU&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=92' },
{ name: 'candyland', url: 'https://www.youtube.com/watch?v=IhchfhxvPKI&ab_channel=Tobu' },
{ name: 'Vicetone - Nevada', url: 'https://www.youtube.com/watch?v=AnMhdn0wJ4I&list=RDQMBlegB1oalTw&index=25' },
{ name: 'Believer ', url: 'https://www.youtube.com/watch?v=FXqp9WiFWzc&list=RDQMBlegB1oalTw&index=17' },
{ name: 'On & On', url: 'https://www.youtube.com/watch?v=XsZZQPKLChY&list=RDQMBlegB1oalTw&index=15' },
{ name: '💋💜Nevada💜💋', url: 'https://www.youtube.com/watch?v=bLrOTFDU2ZI&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=109&ab_channel=Detective.J' },
{ name: 'Legends Never Die', url: 'https://www.youtube.com/watch?v=r6zIGXun57U&list=RDQMBlegB1oalTw&index=3' },
{ name: 'nevada', url: 'https://www.youtube.com/watch?v=2jzxIOCYzEM&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=108&ab_channel=Jarctix' },
{ name: 'Tinh Vệ (精卫) ', url: 'https://www.youtube.com/watch?v=pWAQZ3bg1Qk' },
{ name: '花海DJ (周杰伦 - JayChou)', url: 'https://www.youtube.com/watch?v=8lxgMpheygs' },
{ name: 'Trăng ơi trăng à - 月光呀月光 slow 0.8x', url: 'https://www.youtube.com/watch?v=YIzMUdPA2s4' },
{ name: 'đáy biển', url: 'https://www.youtube.com/watch?v=8Byd6elEkbw' },
{ name: 'chill 4', url: 'https://www.youtube.com/watch?v=-GDI6oT6Jp8&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=2' },
{ name: 'xích linh', url: 'https://www.youtube.com/watch?v=Ba0A_7RKc-k' },
{ name: 'giỏ nổi lên rồi', url: 'https://www.youtube.com/watch?v=n9iKoJ9ZE-Q' },
{ name: 'chill 5', url: 'https://www.youtube.com/watch?v=xZhkxpwkYiA&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=84&pp=gAQBiAQB8AUB' },
{ name: 'nhất lộ sinh hoa', url: 'https://www.youtube.com/watch?v=S1ElLh_hf3k' },
{ name: 'chill 6', url: 'https://www.youtube.com/watch?v=w35LzCA0YLY&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=82&pp=gAQBiAQB8AUB' },
{ name: 'chill 7', url: 'https://www.youtube.com/watch?v=40EAqsXibhM&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=81&pp=gAQBiAQB8AUB' },
{ name: 'chill 8', url: 'https://www.youtube.com/watch?v=J4L-1FLXVLM&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=80&pp=gAQBiAQB8AUB' },
{ name: 'vây giữ', url: 'https://www.youtube.com/watch?v=G_fVwdpLKZ4' },
{ name: 'mười năm nhân gian', url: 'https://www.youtube.com/watch?v=9cSWgDSZ7X0' },
{ name: 'chill 9', url: 'https://www.youtube.com/watch?v=bb5ucM01Em0&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=76&pp=gAQBiAQB8AUB' },
{ name: 'nhân sinh quán', url: 'https://www.youtube.com/watch?v=NxEDFmqWFLo' },
{ name: 'quan sơn tửu', url: 'https://www.youtube.com/watch?v=M6KC0C4aWbA' },
{ name: 'chill 12', url: 'https://www.youtube.com/watch?v=ocfOBZSOwGc&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=72&pp=gAQBiAQB8AUB' },
{ name: 'chill 13', url: 'https://www.youtube.com/watch?v=caf7T4AubSE&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=71&pp=gAQBiAQB8AUB' },
{ name: 'chill 14', url: 'https://www.youtube.com/watch?v=ZhGWQuqE758&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=65&pp=gAQBiAQB8AUB' },
{ name: 'chill 15', url: 'https://www.youtube.com/watch?v=h3aWuBzimTk&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=66&pp=gAQBiAQB8AUB' },
{ name: 'chill 16', url: 'https://www.youtube.com/watch?v=RKF4Tn7P-MQ&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=63&pp=gAQBiAQB8AUB' },
{ name: '红色高跟鞋( giày cao gót màu đỏ )', url: 'https://www.youtube.com/watch?v=muvNBWqtrv4' },
{ name: 'Run Free', url: 'https://www.youtube.com/watch?v=o3KXwe-7A-I&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=60&ab_channel=ATLAST' },
{ name: 'Shadow Of The Sun', url: 'https://www.youtube.com/watch?v=HsM9VucuCtw&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=59&ab_channel=AZURA' },
{ name: 'Cưới Thôi', url: 'https://www.youtube.com/watch?v=JOWqEpONn9w&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=58' },
{ name: 'Ấn Nút Nhớ Thả Giấc Mơ', url: 'https://www.youtube.com/watch?v=sSljdfttEl8&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=58&ab_channel=N26Music%E2%99%AA' },
{ name: 'huan BACK HOME', url: 'https://www.youtube.com/watch?v=8Tx36l5MGxg&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=55&pp=gAQBiAQB8AUB' },
{ name: 'WAY BACK HOME', url: 'https://www.youtube.com/watch?v=1kehqCLudyg&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=54&pp=gAQBiAQB8AUB' },
{ name: 'THAT GIRL', url: 'https://www.youtube.com/watch?v=OUtbNopS4xU&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=53&pp=gAQBiAQB8AUB' },
{ name: 'PRETTY GIRL', url: 'https://www.youtube.com/watch?v=ptIXwyxf7XQ&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=52&pp=gAQBiAQB8AUB' },
{ name: 'DREAM-SAVE ME', url: 'https://www.youtube.com/watch?v=rREz6DYDXng&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=48&pp=gAQBiAQB8AUB' },
{ name: 'ALAN- PLAY', url: 'https://www.youtube.com/watch?v=YQRHrco73g4&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=44&pp=gAQBiAQB8AUB' },
{ name: 'NHAC REVIEW PHIM', url: 'https://www.youtube.com/watch?v=ialVTirpQ5Q&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=43&pp=gAQBiAQB8AUB' },
{ name: 'LOVE IS GONE', url: 'https://www.youtube.com/watch?v=c6SZy7miyaY&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=42&pp=gAQBiAQB8AUB' },
{ name: 'MONODY', url: 'https://www.youtube.com/watch?v=1MZR0BEniIY&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=36&pp=gAQBiAQB8AUB' },
{ name: 'STEORT HEAL', url: 'https://www.youtube.com/watch?v=Y1pq2oLXbTQ&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=33&pp=gAQBiAQB8AUB' },
{ name: 'CLOSE THE SUN', url: 'https://www.youtube.com/watch?v=VyXm3GTdNf0' },
{ name: 'PSYCHO', url: 'https://www.youtube.com/watch?v=YvLRu5vcr68' },
{ name: 'Yami', url: 'https://www.youtube.com/watch?v=eTgxYFXP1hc&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=14&ab_channel=C%C3%A0Chua' },
{ name: 'RETUNR', url: 'https://www.youtube.com/watch?v=m4Hg_JMtJqI&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=15&pp=gAQBiAQB8AUB' },
{ name: 'TOP EDM', url: 'https://www.youtube.com/watch?v=xlTZywrfO7E&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=17&pp=gAQBiAQB8AUB' },
{ name: 'HIS THEME', url: 'https://www.youtube.com/watch?v=qOpsp9bJFP4&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=12&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 17', url: 'https://www.youtube.com/watch?v=ybgvaC4rfAE&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&ab_channel=%F0%9D%90%92%F0%9D%90%9A%F0%9D%90%9D%F0%9D%90%82%F0%9D%90%A1%F0%9D%90%A2%F0%9D%90%A5%F0%9D%90%A5-%F0%9D%90%94%F0%9D%90%92%F0%9D%90%94%F0%9D%90%8A' },
{ name: 'CHILL 18', url: 'https://www.youtube.com/watch?v=-GDI6oT6Jp8&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=2&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 19', url: 'https://www.youtube.com/watch?v=6LW7tcryoXs&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=3&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 20', url: 'https://www.youtube.com/watch?v=6LW7tcryoXs&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=3&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 21', url: 'https://www.youtube.com/watch?v=6I5gYHn-QOk&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=4&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 22', url: 'https://www.youtube.com/watch?v=5sG4k7rj6MY&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=5&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 23', url: 'https://www.youtube.com/watch?v=0wsMSc5hDQg&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=6&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 24', url: 'https://www.youtube.com/watch?v=5TZ33vy_v5w&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=7&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 25', url: 'https://www.youtube.com/watch?v=5TZ33vy_v5w&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=7&pp=gAQBiAQB8AUB' },
{ name: 'Người yêu bỏ lỡ', url: 'https://www.youtube.com/watch?v=DK23U3sJrYg' },
{ name: 'CHILL 26', url: 'https://www.youtube.com/watch?v=gfsUC3F8pYA&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=8&pp=gAQBiAQB8AUB' },
{ name: 'CHILL 27', url: 'https://www.youtube.com/watch?v=zFx0o4epvPA&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=9&pp=gAQBiAQB8AUB' },
{ name: 'intro ( real love )', url: 'https://www.youtube.com/watch?v=66nH4dXp_-o' },
{ name: 'in the end', url: 'https://www.youtube.com/watch?v=WNeLUngb-Xg' },
{ name: '花火が瞬く夜に', url: 'https://www.youtube.com/watch?v=xZ5Rrrul7h8' },
{ name: 'Melancholy', url: 'https://www.youtube.com/watch?v=RxglYGHuqFc' },
{ name: 'Bá hổ thuyết', url: 'https://www.youtube.com/watch?v=6pomVpUk5-Y' },
{ name: 'windy hill', url: 'https://www.youtube.com/watch?v=qV97ux4NA28&pp=ygUKd2luZHkgaGlsbA%3D%3D' },
{ name: '海底 của 一支榴莲', url: 'https://www.youtube.com/watch?v=v5gK8np-OTA' },
{ name: '下辈子还要和你成个家', url: 'https://www.youtube.com/watch?v=6CMITr9dTws' },
{ name: 'past lives', url: 'https://www.youtube.com/watch?v=iNa1n6Gch7E' },
{ name: 'lovely', url: 'https://www.youtube.com/watch?v=8VLXHyHRXjc&pp=ygUGbG92ZWx5' },
{ name: '送给未来的你', url: 'https://www.youtube.com/watch?v=iQfIcgA8qHg' },
{ name: '刚好遇见你 sieu hay', url: 'https://www.youtube.com/watch?v=aEhq4WxBYqM' },
{ name: 'ALAN 2', url: 'https://www.youtube.com/watch?v=jlQ2hs0EANo' },
{ name: 'top chil tq', url: 'https://www.youtube.com/watch?v=2EmGToTikIY' },
{ name: 'My Sunset', url: 'https://www.youtube.com/watch?v=GpkHJlyV7TQ' },
{ name: 'Quan sơn tửu', url: 'https://www.youtube.com/watch?v=wvkGE4mtTB0' },
{ name: 'Lifeline', url: 'https://www.youtube.com/watch?v=rWTmSHXVfCM' },
{ name: 'dancing with your ghost', url: 'https://www.youtube.com/watch?v=emm0uGDGg2o' },
{ name: 'shape of you', url: 'https://www.youtube.com/watch?v=Ksin3zNXvzo' },
{ name: 'seasons', url: 'https://www.youtube.com/watch?v=Ymts4ldfPws' },
{ name: 'L.I.F.E', url: 'https://www.youtube.com/watch?v=_tSWg-KOslM' },
{ name: 'summersong', url: 'https://www.youtube.com/watch?v=HoCw_gaCHXE' },
{ name: '芒种" (Mang Chủng)', url: 'https://www.youtube.com/watch?v=vgbrIy08e2w' },
{ name: 'china-X', url: 'https://www.youtube.com/watch?v=qgVXS8l5smo' },
{ name: 'breathe', url: 'https://www.youtube.com/watch?v=KbT-qpE3Kl4' },
{ name: 'dynasty', url: 'https://www.youtube.com/watch?v=5OESzopq3dE' },
{ name: 'Hồng chiêu nguyện', url: 'https://www.youtube.com/watch?v=lbNPMskXNHo' },
{ name: '20 EDM tq', url: 'https://www.youtube.com/watch?v=IAMbG8OiExU' },
{ name: 'top nhac', url: 'https://www.youtube.com/watch?v=u5WZnV3AoA4' },
{ name: 'Closer', url: 'https://www.youtube.com/watch?v=PT2_F-1esPk&ab_channel=ChainsmokersVEVO' },
{ name: 'dusk till dawn', url: 'https://www.youtube.com/watch?v=p-eS-_olx9M&ab_channel=7clouds' },
{ name: 'Mood ', url: 'https://www.youtube.com/watch?v=f1J4dRTMy9A&ab_channel=7clouds' },
{ name: 'royalty', url: 'https://www.youtube.com/watch?v=oOi3oJmfz4o&ab_channel=7clouds' },
{ name: 'Nova', url: 'https://www.youtube.com/watch?v=Rq-0NxKUR-Y&ab_channel=SrMichi' },
{ name: 'Fight', url: 'https://www.youtube.com/watch?v=EVpm3pHYaV4&ab_channel=BeatBrothers' },
{ name: 'First Date', url: 'https://www.youtube.com/watch?v=AVK0BIVqLLc&ab_channel=frad' },
{ name: 'Vacation', url: 'https://www.youtube.com/watch?v=TidRG-baYi8&ab_channel=Nh%E1%BA%ADtH%E1%BA%A3oTr%E1%BA%A7n' },
{ name: 'anh thanh niên', url: 'https://www.youtube.com/watch?v=HPL74s4VPdk&pp=ygUPYW5oIHRoYW5oIG5pw6pu' },
{ name: 'kẹo bông ngòn ', url: 'https://www.youtube.com/watch?v=sHa5nQO3jwA&ab_channel=H2KMusic' },
{ name: 'Mây x Gió', url: 'https://www.youtube.com/watch?v=0A6hCfFZVj4&ab_channel=DuzmeMusic' },
{ name: 'spectre', url: 'https://www.youtube.com/watch?v=wJnBTPUQS5A' },
{ name: 'alone', url: 'https://www.youtube.com/watch?v=1-xGerv5FOk' },
{ name: 'faded', url: 'https://www.youtube.com/watch?v=60ItHLz5WEA' },
{ name: 'chill 28', url: 'https://www.youtube.com/watch?v=4vayrx6PFCQ&ab_channel=AGNES%F0%9F%94%A5' },
{ name: 'chill 29', url: 'https://www.youtube.com/watch?v=icxO53ZyK7A' },
{ name: 'chill 30', url: 'https://www.youtube.com/watch?v=AQbvCfRCFvg' },
{ name: 'On my way', url: 'https://www.youtube.com/watch?v=ETqXUBFZpkE&ab_channel=LOFI_LINES' },
{ name: 'Nothin On Me', url: 'https://www.youtube.com/watch?v=qmbB3uR92j8&ab_channel=H%E1%BB%A7Mu%E1%BB%91iM%E1%BA%B7n' },
{ name: 'PIXELS', url: 'https://www.youtube.com/watch?v=EUyQgyzpAbE&ab_channel=brianjcb' },
{ name: 'Nothing on you', url: 'https://www.youtube.com/watch?v=U573mlR4rYw&ab_channel=DuskMusicASIA' },
{ name: 'So Far Away ', url: 'https://www.youtube.com/watch?v=rA0jSPEoyk4&ab_channel=ITMMUSIC' },
{ name: 'sold out', url: 'https://www.youtube.com/watch?v=clKvFcl0zwo&ab_channel=LyricsMusic' },
{ name: 'the way still love you', url: 'https://www.youtube.com/watch?v=MsBEu1iWsF4&ab_channel=TopTikTok' },
{ name: 'Thăm cố tri', url: 'https://www.youtube.com/watch?v=409xjHOU63E' },
{ name: 'top tq sieu chill', url: 'https://www.youtube.com/watch?v=TmRvke5Ue-k&ab_channel=Tr.T.Kh%C3%A1nhHuy%E1%BB%81n' },
{ name: 'Reverse溯 (版钢琴', url: 'https://www.youtube.com/watch?v=v7xRVTXWkbU&ab_channel=HyQMusic%E3%83%84' },
{ name: 'DEATH BED', url: 'https://www.youtube.com/watch?v=jJPMnTXl63E&list=PLB8Tk-JabtWed_6pE4H7yqctxbntnjwEe&index=10&pp=gAQBiAQB8AUB' },
{ name: 'Cry For Me x Giày Cao Gót Màu Đỏ', url: 'https://www.youtube.com/watch?v=2OM6Y_kunAM' },
{ name: 'Cry For Me', url: 'https://www.youtube.com/watch?v=72hp9Bqfpz4&pp=ygULY3J5IGZvciBtZSA%3D' },
{ name: 'Kiếp sau chắc sẽ không còn gặp được anh', url: 'https://www.youtube.com/watch?v=uhlYZ5b91RA' },
{ name: 'china p', url: 'https://www.youtube.com/watch?v=-3vdk1Qf4mI' },
{ name: 'china rain', url: 'https://www.youtube.com/watch?v=GqC8jWzmiLA' },
{ name: 'Erik Lund - Summertime', url: 'https://www.youtube.com/watch?v=uuiA9Htp1xQ' },
{ name: 'ightning ocean deed', url: 'https://www.youtube.com/watch?v=tW7oWvb-76Q' },
{ name: 'are you lost - park bird', url: 'https://www.youtube.com/watch?v=PJgEu_Ecuf8' },
{ name: 'Back one day', url: 'https://www.youtube.com/watch?v=2QdPxdcMhFQ' },
{ name: 'Collapsing world', url: 'https://www.youtube.com/watch?v=sOSqUMZgfoE' },
{ name: '所念皆星河 ( Nỗi nhớ tựa thiên hà )', url: 'https://www.youtube.com/watch?v=Mkwn5MHsJa0' },
{ name: 'Komorebi', url: 'https://www.youtube.com/watch?v=v1up3zGBYZU' },
{ name: '城南花已开 ( Thành nam hoa nở )', url: 'https://www.youtube.com/watch?v=AhlsPpuILuk' },
{ name: '告白之夜 ( Đêm tỏ tình )', url: 'https://www.youtube.com/watch?v=vMK1kuJGgnQ' },
{ name: '幻昼', url: 'https://www.youtube.com/watch?v=9eWNB_aMi-s' },
{ name: 'My soul', url: 'https://www.youtube.com/watch?v=935RgNLNuno' },
{ name: '青空 ( Bầu trời xanh )', url: 'https://www.youtube.com/watch?v=TkAOz9m-HNk' },
{ name: 'origin', url: 'https://www.youtube.com/watch?v=gZIDNZh9U14' },
{ name: 'let me love you x we dont talk anymore', url: 'https://www.youtube.com/watch?v=Boyvu7-wO1I' },
{ name: 'Normal no more', url: 'https://www.youtube.com/watch?v=iGrN7Gb8DtI' },
{ name: 'flower day piano', url: 'https://www.youtube.com/watch?v=asUUKGlCvDM' },
{ name: 'golden hour', url: 'https://www.youtube.com/watch?v=PEM0Vs8jf1w' },
{ name: 'sky blue', url: 'https://www.youtube.com/watch?v=BiwAlE4Inok' },
{ name: 'before spring ends', url: 'https://www.youtube.com/watch?v=s75xe7wKxSM' },
{ name: 'ha chi chua toi piano', url: 'https://www.youtube.com/watch?v=XN4PhnVfZt4' },
{ name: 'forest mixtape', url: 'https://www.youtube.com/watch?v=kwdeazF4j2o' },
{ name: 'điều anh biết', url: 'https://www.youtube.com/watch?v=ocjUUfk9k1Y' },
{ name: 'chúng ta không thuộc về nhau', url: 'https://www.youtube.com/watch?v=qGRU3sRbaYw' },
{ name: 'Nắng Lung Linh ', url: 'https://www.youtube.com/watch?v=wO9r4kj-ErU' },
{ name: ' 100 years love', url: 'https://www.youtube.com/watch?v=47ahoiV9qGY' },
{ name: 'Chưa chắc remix', url: 'https://www.youtube.com/watch?v=dpYG7NQL8oM' },
{ name: 'Đường Tôi Chở Em Về', url: 'https://www.youtube.com/watch?v=OuNo8Tkb3lI' },
{ name: 'Nụ Cười Của Cô Ấy', url: 'https://www.youtube.com/watch?v=EVcwgI-dLBg' },
{ name: 'Phonecert mashup', url: 'https://www.youtube.com/watch?v=dcQwM3KPXWc' },
{ name: 'chill 31', url: 'https://www.youtube.com/watch?v=tVQ_uDRs_7U' },
{ name: 'chill 32', url: 'https://www.youtube.com/watch?v=b-FHfiM8ILo' },
{ name: 'chill 33', url: 'https://www.youtube.com/watch?v=UqOnN8Qnh4Y' },
{ name: 'chill 34', url: 'https://www.youtube.com/watch?v=i9rBIgU0Lps' },
{ name: 'chill 35', url: 'https://www.youtube.com/watch?v=ZX2mjf9dFH8' },
{ name: 'chill 36', url: 'https://www.youtube.com/watch?v=F4JgISE0zdc' },
{ name: 'chill 37', url: 'https://www.youtube.com/watch?v=CCgt6IwzZoU' },
{ name: 'chill 38', url: 'https://www.youtube.com/watch?v=1bMg6REj2HU' },
{ name: 'chill 39', url: 'https://www.youtube.com/watch?v=vcwszTnFkIY&list=RDGMEMCMFH2exzjBeE_zAHHJOdxg&start_radio=1&rv=1bMg6REj2HU' },
{ name: 'Không hẹn gặp lại', url: 'https://www.youtube.com/watch?v=MAd0QlVRYWc&list=RDGMEMCMFH2exzjBeE_zAHHJOdxg&index=11' },
{ name: 'Call of Silence', url: 'https://www.youtube.com/watch?v=SVBvYbobwEw&list=RDGMEMCMFH2exzjBeE_zAHHJOdxg&index=13' },
{ name: 'chill 40', url: 'https://www.youtube.com/watch?v=oEwrAwb_4jM' },
{ name: 'chill 41', url: 'https://www.youtube.com/watch?v=nN4PvclzdIc' },
{ name: '[小红书]《02》', url: 'https://www.youtube.com/watch?v=wqbk6ZJ8jhs' },
{ name: ' Gặp gỡ đã là quẻ Thượng Thượng ', url: 'https://www.youtube.com/watch?v=_3o-qe3IRYM' },
{ name: 'Beyond The Sea Is Freedom (完整版)', url: 'https://www.youtube.com/watch?v=dxDhOf727rg' },
{ name: 'chill 40', url: 'https://www.youtube.com/watch?v=yMuBSxSIS04&t' },
{ name: 'Night crusing', url: 'https://www.youtube.com/watch?v=TCtG_SJF6As' }
];
let currentPlayingID = null;
let currentButton = null;
// Initialize music list
const musicItemContainer = document.createElement('div');
musicList.forEach((music, idx) => addMusicButton(music, idx));
musicMenuContainer.appendChild(musicItemContainer);
document.body.appendChild(musicMenuContainer);
// ==================== PHẦN TÌM KIẾM BÀI HÁT ====================
// Tạo container cho tìm kiếm
const searchContainer = document.createElement('div');
searchContainer.style.marginBottom = '15px';
searchContainer.style.padding = '12px';
searchContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.25)';
searchContainer.style.borderRadius = '12px';
searchContainer.style.border = '1px solid rgba(255, 255, 255, 0.25)';
// Input tìm kiếm
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.placeholder = '🔍 Tìm bài hát...';
searchInput.style.width = '100%';
searchInput.style.padding = '10px';
searchInput.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
searchInput.style.border = '1px solid rgba(255, 255, 255, 0.2)';
searchInput.style.borderRadius = '30px';
searchInput.style.color = '#fff';
searchInput.style.fontSize = '13px';
searchInput.style.outline = 'none';
searchInput.style.transition = 'all 0.3s';
searchInput.addEventListener('focus', () => {
searchInput.style.backgroundColor = 'rgba(255, 255, 255, 0.15)';
searchInput.style.borderColor = 'rgba(76, 175, 80, 0.5)';
});
searchInput.addEventListener('blur', () => {
searchInput.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
searchInput.style.borderColor = 'rgba(255, 255, 255, 0.2)';
});
// Container hiển thị kết quả tìm kiếm
const searchResultsContainer = document.createElement('div');
searchResultsContainer.style.marginTop = '10px';
searchResultsContainer.style.maxHeight = '300px';
searchResultsContainer.style.overflowY = 'auto';
searchResultsContainer.style.display = 'none';
// Thêm vào menu
searchContainer.appendChild(searchInput);
searchContainer.appendChild(searchResultsContainer);
// Chèn vào trước danh sách nhạc (musicItemContainer)
musicMenuContainer.insertBefore(searchContainer, musicItemContainer);
// Hàm lọc và hiển thị kết quả
function updateSearchResults() {
const keyword = searchInput.value.trim().toLowerCase();
if (keyword === '') {
searchResultsContainer.style.display = 'none';
musicItemContainer.style.display = 'block';
return;
}
// Lọc bài hát
const filtered = musicList.filter(music => music.name && music.name.toLowerCase().includes(keyword));
if (filtered.length === 0) {
searchResultsContainer.innerHTML = '<div style="text-align:center; padding:15px; color:rgba(255,255,255,0.25);">Không tìm thấy bài hát nào 😢</div>';
} else {
// Tạo danh sách kết quả
let html = '';
filtered.forEach(music => {
html += `
<button class="search-result-btn" data-name="${music.name.replace(/"/g, '"')}" data-url="${music.url}" style="
width: 100%;
padding: 10px;
margin-bottom: 8px;
background: rgba(0, 255, 255, 0.1);
border: 1px solid rgba(0, 255, 255, 0.2);
border-radius: 10px;
color: #fff;
font-size: 12px;
text-align: left;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
">🎵 ${music.name}</button>
`;
});
searchResultsContainer.innerHTML = html;
// Gắn sự kiện click cho từng nút kết quả
document.querySelectorAll('.search-result-btn').forEach(btn => {
btn.addEventListener('click', () => {
const name = btn.getAttribute('data-name');
const url = btn.getAttribute('data-url');
const music = { name, url };
// Tìm nút tương ứng trong danh sách gốc (nếu có) để cập nhật trạng thái
const originalButtons = musicItemContainer.querySelectorAll('button');
let targetButton = null;
for (let i = 0; i < originalButtons.length; i++) {
if (originalButtons[i].textContent.includes(name)) {
targetButton = originalButtons[i];
break;
}
}
playMusic(music, targetButton || btn);
// Ẩn kết quả tìm kiếm sau khi chọn
searchInput.value = '';
searchResultsContainer.style.display = 'none';
musicItemContainer.style.display = 'block';
});
});
}
searchResultsContainer.style.display = 'block';
musicItemContainer.style.display = 'none';
}
// Lắng nghe sự kiện input
searchInput.addEventListener('input', updateSearchResults);
// Thêm style cho scrollbar trong kết quả tìm kiếm
const searchStyle = document.createElement('style');
searchStyle.textContent = `
#musicMenuContainer .search-results-container::-webkit-scrollbar {
width: 5px;
}
#musicMenuContainer .search-results-container::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
}
#musicMenuContainer .search-results-container::-webkit-scrollbar-thumb {
background: rgba(0, 255, 255, 0.3);
border-radius: 10px;
}
.search-result-btn:hover {
background: rgba(0, 255, 255, 0.25) !important;
transform: translateX(5px);
}
`;
document.head.appendChild(searchStyle);
// ==================== KẾT THÚC PHẦN TÌM KIẾM ====================
function addMusicButton(music, index) {
const musicItem = document.createElement('div');
musicItem.style.display = 'flex';
musicItem.style.alignItems = 'center';
musicItem.style.marginBottom = '10px';
const musicButton = createButton(music.name + ' (nghe thử xem)', 'rgba(0, 255, 255, 0.25)');
musicButton.addEventListener('click', () => {
playMusic(music, musicButton);
});
musicItem.appendChild(musicButton);
musicItemContainer.appendChild(musicItem);
musicButtons.push(musicButton); // lưu button để dùng cho auto next
}
// Hàm phát bài tiếp theo (theo thứ tự)
function playNextSong() {
if (!sequentialMode) return;
if (musicList.length === 0) return;
let nextIndex = (currentMusicIndex + 1) % musicList.length;
// Nếu không tìm thấy index hiện tại (có thể do chưa có bài nào phát) thì chọn bài đầu
if (currentMusicIndex === -1) nextIndex = 0;
const nextMusic = musicList[nextIndex];
const nextButton = musicButtons[nextIndex] || null;
playMusic(nextMusic, nextButton);
}
// Play the selected music
function playMusic(music, musicButton) {
if (currentPlayingID && currentButton) {
player.stopVideo();
currentButton.textContent = currentButton.textContent.replace(' (Chill nào)', ' (nghe thử xem)');
currentButton.style.color = '#fff';
}
const videoID = extractVideoID(music.url);
if (videoID) {
currentMusic = music;
// Cập nhật chỉ số bài hiện tại
currentMusicIndex = musicList.findIndex(m => m.url === music.url);
if (currentMusicIndex === -1) currentMusicIndex = 0;
player.loadVideoById(videoID);
player.playVideo();
currentPlayingID = videoID;
currentButton = musicButton;
musicButton.textContent = music.name + ' (Chill nào)';
musicButton.style.color = 'lightgreen';
}
}
// Create buttons for volume, speed, etc.
function createButton(text, bgColor) {
const button = document.createElement('button');
button.textContent = text;
button.style.width = '100%';
button.style.padding = '10px';
button.style.backgroundColor = bgColor;
button.style.color = '#fff';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.cursor = 'pointer';
button.style.transition = 'background-color 0.3s';
button.addEventListener('mouseover', () => {
button.style.backgroundColor = 'rgba(255, 255, 255, 0.25)';
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = bgColor;
});
return button;
}
// Create a slider
function createSlider(min, max, defaultValue) {
const slider = document.createElement('input');
slider.type = 'range';
slider.min = min;
slider.max = max;
slider.value = defaultValue;
slider.style.width = '100%';
slider.style.marginBottom = '10px';
return slider;
}
// Create a select dropdown
function createSelect(options, suffix) {
const select = document.createElement('select');
options.forEach(option => {
const opt = document.createElement('option');
opt.value = option;
opt.textContent = `${option}${suffix}`;
select.appendChild(opt);
});
select.style.width = '100%';
return select;
}
// Create an invisible player container
const playerContainer = document.createElement('div');
playerContainer.id = 'musicPlayer';
playerContainer.style.position = 'fixed';
playerContainer.style.bottom = '0';
playerContainer.style.right = '0';
playerContainer.style.width = '0';
playerContainer.style.height = '0';
document.body.appendChild(playerContainer);
// Load YouTube IFrame Player API
let tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
let firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Create YouTube player
let player;
window.onYouTubeIframeAPIReady = function() {
player = new YT.Player('musicPlayer', {
height: '0',
width: '0',
videoId: '',
playerVars: {
'autoplay': 1,
'controls': 0,
'mute': 0,
'vq': 'hd1080',
'iv_load_policy': 3
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
};
function onPlayerReady(event) {
console.log('YouTube Player is ready');
player.setVolume(85);
audioEngine.init().then(() => {
setTimeout(() => {
try {
const iframe = player.getIframe();
const videoEl = iframe.contentDocument?.querySelector('video');
if (videoEl) {
audioEngine.connectToVideo(videoEl);
}
} catch (e) {}
}, 2000);
});
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.PLAYING) {
updateDurationDisplay();
if (window.progressInterval) {
clearInterval(window.progressInterval);
}
window.progressInterval = setInterval(updateProgressBar, 1000);
}
if (event.data === YT.PlayerState.ENDED) {
if (loopMode === 'single' && currentMusic) {
// Lặp lại bài hiện tại
const videoID = extractVideoID(currentMusic.url);
if (videoID) {
player.loadVideoById(videoID);
player.playVideo();
}
} else if (sequentialMode) {
// Tự động chuyển bài tiếp theo
playNextSong();
}
}
}
function updateDurationDisplay() {
const duration = player.getDuration();
durationDisplay.textContent = `thời gian: ${formatTime(player.getCurrentTime())} / ${formatTime(duration)}`;
progressBar.max = duration;
}
function updateProgressBar() {
if (player && currentPlayingID) {
progressBar.value = player.getCurrentTime();
updateDurationDisplay();
}
}
function formatTime(seconds) {
if (!seconds || isNaN(seconds)) return '0:00';
const minutes = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${minutes}:${secs < 10 ? '0' + secs : secs}`;
}
function extractVideoID(url) {
const videoIDMatch = url.match(/(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
return videoIDMatch ? videoIDMatch[1] : null;
}
document.addEventListener('keydown', (event) => {
if (event.key === 'Tab') {
musicMenuContainer.style.display = musicMenuContainer.style.display === 'block' ? 'none' : 'block';
}
if (event.key === ']') {
musicMenuContainer.style.display = musicMenuContainer.style.display === 'block' ? 'none' : 'block';
}
if (event.key === ' ') {
pauseButton.click();
}
if (event.key === 's' || event.key === 'S') {
stopButton.click();
}
});
musicMenuContainer.style.display = 'block';
// ==================== CẬP NHẬT ĐỒNG HỒ VÀ ĐỀ XUẤT BÀI HÁT ====================
function updateSuggestion() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
clockDiv.textContent = `${hours}:${minutes}:${seconds}`;
// Tính tổng số giây trong ngày
const totalSeconds = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds();
// Lấy danh sách bài hát hợp lệ (có tên và url)
const validSongs = musicList.filter(song => song.name && song.url);
if (validSongs.length > 0) {
const index = totalSeconds % validSongs.length;
const suggested = validSongs[index];
suggestedSongDiv.innerHTML = `🎧 <strong>Đề xuất:</strong> ${suggested.name}`;
// Lưu bài hát đề xuất để nút phát sử dụng
playSuggestBtn.onclick = () => {
// Tìm nút tương ứng trong danh sách (nếu có) để cập nhật trạng thái
const originalButtons = musicItemContainer.querySelectorAll('button');
let targetButton = null;
for (let i = 0; i < originalButtons.length; i++) {
if (originalButtons[i].textContent.includes(suggested.name)) {
targetButton = originalButtons[i];
break;
}
}
playMusic(suggested, targetButton || playSuggestBtn);
};
} else {
suggestedSongDiv.innerHTML = '🎧 Không có bài hát nào để đề xuất.';
playSuggestBtn.onclick = null;
}
}
updateSuggestion();
setInterval(updateSuggestion, 1000);
})();
// ==================== PHẦN 2: MENU SỐ 2 (GIỮ NGUYÊN) ====================
(function () {
'use strict';
const menu = document.createElement('div');
menu.id = 'music-menu';
menu.style.position = 'fixed';
menu.style.top = '0';
menu.style.right = '-300px';
menu.style.width = '250px';
menu.style.height = '100%';
menu.style.backgroundColor = 'rgba(0, 0, 0, 0.25)';
menu.style.color = '#fff';
menu.style.fontFamily = 'Arial, sans-serif';
menu.style.padding = '20px';
menu.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.25)';
menu.style.transition = 'right 0.5s ease';
menu.style.zIndex = '10000';
menu.innerHTML = `
<h2 style="text-align: center;" id="music-menu-title">Hudební menu</h2>
<label for="music-url" id="music-url-label">URL písničky (YouTube):</label>
<input id="music-url" type="text" style="width: 100%; margin-bottom: 10px; padding: 5px;" placeholder="cho link ytb vào đây....">
<label for="start-time" id="start-time-label">Start Time Seconds...):</label>
<input id="start-time" type="number" style="width: 100%; margin-bottom: 10px; padding: 5px;" placeholder="giây...">
<!-- ==================== THÊM NÚT LOOP CHO MENU 2 ==================== -->
<button id="loop-menu2" style="width: 100%; padding: 10px; margin-bottom: 10px; background-color: #9E9E9E; color: white; border: none; cursor: pointer; font-size: 16px; font-weight: bold; border-radius: 5px;">➡️ Không lặp</button>
<button id="play-music" style="width: 100%; padding: 10px; margin-bottom: 10px; background-color: #4CAF50; color: white; border: none; cursor: pointer; font-size: 16px; font-weight: bold; border-radius: 5px;">Přehrát písničku</button>
<button id="start-video" style="width: 100%; padding: 10px; margin-bottom: 10px; background-color: #2196F3; color: white; border: none; cursor: pointer; font-size: 16px; font-weight: bold; border-radius: 5px;">START VIDEO</button>
<button id="stop-music" style="width: 100%; padding: 10px; background-color: #f44336; color: white; border: none; cursor: pointer; font-size: 16px; font-weight: bold; border-radius: 5px;">Zastavit</button>
<div id="video-container" style="margin-top: 20px; display: none;">
<iframe id="video-frame" width="100%" height="200" style="border: none;" src="" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<div id="player" style="margin-top: 20px; display: none;"></div>
<div id="warning" style="margin-top: 20px; color: red; font-weight: bold;">
<p id="adblock-warning">POUŽITÍ ADBLOCKU VEDE K NEFUNKČNOSTI VYPNITE HO</p>
<label for="language-select" style="color: white;">Language:</label>
<select id="language-select" style="width: 100%; padding: 5px;">
<option value="cz">Čeština</option>
<option value="en">English</option>
<option value="ru">Русский</option>
<option value="vi">Tiếng Việt</option>
<option value="ar">العربية</option>
</select>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
Script By <a href="https://www.youtube.com/@RektByMateX" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">RektByMateX</a>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB2B;">
truy cập nhanh (quick access)
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
1 <a href="https://www.youtube.com" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">youtube</a>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
2 <a href="https://translate.google.com" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">translate.google</a>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
3 <a href="https://facebook.com" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">facebook</a>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
4 <a href="https://discord.com/channels/@me" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">discord</a>
</div>
<div style="margin-top: 20px; text-align: center; font-weight: bold; color: #FFEB3B;">
5 <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley" target="_blank" style="color: #FF4081; font-weight: bold; text-decoration: underline;">hmmmmmm</a>
</div>
`;
document.body.appendChild(menu);
let menuVisible = false;
let loopMode2 = 'none';
let currentVideoId2 = null;
function toggleMenu() {
menu.style.right = menuVisible ? '-300px' : '0';
menuVisible = !menuVisible;
console.log('Menu visible:', menuVisible);
}
const loopBtn2 = document.getElementById('loop-menu2');
loopBtn2.addEventListener('click', () => {
if (loopMode2 === 'none') {
loopMode2 = 'single';
loopBtn2.textContent = '🔂 Lặp bài này';
loopBtn2.style.backgroundColor = '#4CAF50';
} else {
loopMode2 = 'none';
loopBtn2.textContent = '➡️ Không lặp';
loopBtn2.style.backgroundColor = '#9E9E9E';
}
});
let player;
function createYouTubePlayer(videoId, startTime) {
currentVideoId2 = videoId;
if (!player) {
player = new YT.Player('player', {
height: '0',
width: '0',
videoId: videoId,
playerVars: {
autoplay: 1,
start: startTime,
vq: 'hd1080',
iv_load_policy: 3
},
events: {
onReady: (event) => {
event.target.playVideo();
setTimeout(() => {
try {
const iframe = player.getIframe();
const videoEl = iframe.contentDocument?.querySelector('video');
if (videoEl) {
audioEngine.connectToVideo(videoEl);
}
} catch (e) {}
}, 2000);
},
onStateChange: (event) => {
if (event.data === YT.PlayerState.ENDED) {
if (loopMode2 === 'single' && currentVideoId2) {
player.loadVideoById(currentVideoId2, startTime);
}
}
}
}
});
} else {
player.loadVideoById(videoId, startTime);
}
}
function stopYouTubePlayer() {
if (player) {
player.stopVideo();
}
const iframe = document.getElementById('video-frame');
iframe.src = '';
document.getElementById('player').style.display = 'none';
document.getElementById('video-container').style.display = 'none';
}
document.getElementById('play-music').addEventListener('click', () => {
const url = document.getElementById('music-url').value;
const startTime = parseInt(document.getElementById('start-time').value) || 0;
const videoId = extractYouTubeVideoId(url);
if (videoId) {
createYouTubePlayer(videoId, startTime);
document.getElementById('player').style.display = 'block';
document.getElementById('video-container').style.display = 'none';
} else {
alert('Neplatný YouTube odkaz.');
}
});
document.getElementById('start-video').addEventListener('click', () => {
const url = document.getElementById('music-url').value;
const startTime = parseInt(document.getElementById('start-time').value) || 0;
const videoId = extractYouTubeVideoId(url);
if (videoId) {
const iframe = document.getElementById('video-frame');
iframe.src = `https://www.youtube.com/embed/${videoId}?start=${startTime}&autoplay=1`;
document.getElementById('video-container').style.display = 'block';
document.getElementById('player').style.display = 'none';
} else {
alert('Neplatný YouTube odkaz.');
}
});
document.getElementById('stop-music').addEventListener('click', () => {
stopYouTubePlayer();
});
document.addEventListener('keydown', (e) => {
if (e.key.toLowerCase() === '[') {
toggleMenu();
}
if (e.key.toLowerCase() === '`') {
toggleMenu();
}
});
function extractYouTubeVideoId(url) {
const match = url.match(/(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
return match ? match[1] : null;
}
const script = document.createElement('script');
script.src = 'https://www.youtube.com/iframe_api';
document.head.appendChild(script);
document.getElementById('language-select').addEventListener('change', (e) => {
changeLanguage(e.target.value);
});
function changeLanguage(language) {
const translations = {
cz: {
'music-menu-title': 'Hudební menu',
'music-url-label': 'URL písničky (YouTube):',
'start-time-label': 'Začátek (sekundy):',
'play-music': 'Přehrát písničku',
'start-video': 'Spustit Video',
'stop-music': 'Zastavit',
'adblock-warning': 'POUŽITÍ ADBLOCKU VEDE K NEFUNKČNOSTI VYPNITE HO',
'language-btn': 'Vyberte jazyk'
},
en: {
'music-menu-title': 'Music Menu',
'music-url-label': 'Song URL (YouTube):',
'start-time-label': 'Start time (seconds):',
'play-music': 'Play Song',
'start-video': 'START VIDEO',
'stop-music': 'Stop',
'adblock-warning': 'USING ADBLOCK CAUSES FAILURE, PLEASE DISABLE IT',
'language-btn': 'Languages'
},
ru: {
'music-menu-title': 'Музыкальное меню',
'music-url-label': 'URL песни (YouTube):',
'start-time-label': 'Время начала (секунды):',
'play-music': 'Воспроизвести песню',
'start-video': 'Запустить видео',
'stop-music': 'Остановить',
'adblock-warning': 'Использование Adblock вызывает сбой, пожалуйста, отключите его',
'language-btn': 'Языки'
},
vi: {
'music-menu-title': 'Menu Nhạc',
'music-url-label': 'URL bài hát (YouTube):',
'start-time-label': 'Thời gian bắt đầu (giây):',
'play-music': 'Phát bài hát',
'start-video': 'Bắt đầu Video',
'stop-music': 'Dừng',
'adblock-warning': 'SỬ DỤNG ADBLOCK GÂY LỖI, VUI LÒNG TẮT NÓ',
'language-btn': 'Ngôn ngữ'
},
ar: {
'music-menu-title': 'قائمة الموسيقى',
'music-url-label': 'رابط الأغنية (YouTube):',
'start-time-label': 'وقت البداية (ثواني):',
'play-music': 'تشغيل الأغنية',
'start-video': 'تشغيل الفيديو',
'stop-music': 'إيقاف',
'adblock-warning': 'استخدام Adblock يؤدي إلى عطل ، يرجى تعطيله',
'language-btn': 'اللغات'
}
};
const text = translations[language] || translations.en;
document.getElementById('music-menu-title').textContent = text['music-menu-title'];
document.getElementById('music-url-label').textContent = text['music-url-label'];
document.getElementById('start-time-label').textContent = text['start-time-label'];
document.getElementById('play-music').textContent = text['play-music'];
document.getElementById('start-video').textContent = text['start-video'];
document.getElementById('stop-music').textContent = text['stop-music'];
document.getElementById('adblock-warning').textContent = text['adblock-warning'];
document.getElementById('language-btn').textContent = text['language-btn'];
}
})();
// ==================== PHẦN 3: TABLE GRADIENT (GIỮ NGUYÊN) ====================
(function () {
'use strict'
const POLL_INTERVAL = 1000
const HUE_RANGE = 120
const SATURATION = '80%'
const LIGHTNESS = '88%'
function applyGradientToColumn(table, column) {
const rowCount = table.rows.length
Array.from(table.rows).forEach((row, index) => {
const cell = row.cells[column]
if (!cell) return
const hue = (index / (rowCount - 1)) * HUE_RANGE
cell.style.backgroundColor = `hsl(${HUE_RANGE - hue}, ${SATURATION}, ${LIGHTNESS})`
})
}
function initializeTable(table) {
if (table.hasAttribute('data-gradient-initialized')) return
table.setAttribute('data-gradient-initialized', 'true')
const columnCount = table.rows[0]?.cells.length || 0
for (let col = 0; col < columnCount; col++) {
applyGradientToColumn(table, col)
}
}
function initializeTables() {
document.querySelectorAll('table:not([data-gradient-initialized])').forEach(initializeTable)
}
initializeTables()
setInterval(initializeTables, POLL_INTERVAL)
})();
// ==================== PHẦN 4: FACEBOOK DOWNLOADER (GIỮ NGUYÊN) ====================
(function () {
'use strict';
function getOverlapScore(el) {
var rect = el.getBoundingClientRect();
return (
Math.min(
rect.bottom,
window.innerHeight || document.documentElement.clientHeight
) - Math.max(0, rect.top)
);
}
function getVideoIdFromVideoElement(video) {
try {
for (let k in video.parentElement) {
if (k.startsWith("__reactProps")) {
return video.parentElement[k].children.props.videoFBID;
}
}
} catch (e) {
return null;
}
}
async function getWatchingVideoId() {
let allVideos = Array.from(document.querySelectorAll("video"));
let result = [];
for (let video of allVideos) {
let videoId = getVideoIdFromVideoElement(video);
if (videoId) {
result.push({
videoId,
overlapScore: getOverlapScore(video),
playing: !!(
video.currentTime > 0 &&
!video.paused &&
!video.ended &&
video.readyState > 2
),
});
}
}
let playingVideo = result.find((_) => _.playing);
if (playingVideo) return [playingVideo.videoId];
return result
.filter((_) => _.videoId && (_.overlapScore > 0 || _.playing))
.sort((a, b) => b.overlapScore - a.overlapScore)
.map((_) => _.videoId);
}
async function getVideoUrlFromVideoId(videoId) {
let dtsg = await getDtsg();
try {
return await getLinkFbVideo2(videoId, dtsg);
} catch (e) {
return await getLinkFbVideo1(videoId, dtsg);
}
}
async function getLinkFbVideo2(videoId, dtsg) {
let res = await fetch(
"https://www.facebook.com/video/video_data_async/?video_id=" + videoId,
{
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: stringifyVariables({
__a: "1",
fb_dtsg: dtsg,
}),
}
);
let text = await res.text();
text = text.replace("for (;;);", "");
let json = JSON.parse(text);
const { hd_src, hd_src_no_ratelimit, sd_src, sd_src_no_ratelimit } =
json?.payload || {};
return hd_src_no_ratelimit || hd_src || sd_src_no_ratelimit || sd_src;
}
async function getLinkFbVideo1(videoId, dtsg) {
let res = await fetchGraphQl("5279476072161634", {
UFI2CommentsProvider_commentsKey: "CometTahoeSidePaneQuery",
caller: "CHANNEL_VIEW_FROM_PAGE_TIMELINE",
displayCommentsContextEnableComment: null,
displayCommentsContextIsAdPreview: null,
displayCommentsContextIsAggregatedShare: null,
displayCommentsContextIsStorySet: null,
displayCommentsFeedbackContext: null,
feedbackSource: 41,
feedLocation: "TAHOE",
focusCommentID: null,
privacySelectorRenderLocation: "COMET_STREAM",
renderLocation: "video_channel",
scale: 1,
streamChainingSection: !1,
useDefaultActor: !1,
videoChainingContext: null,
videoID: videoId,
}, dtsg);
let text = await res.text();
let a = JSON.parse(text.split("\n")[0]),
link = a.data.video.playable_url_quality_hd || a.data.video.playable_url;
return link;
}
function fetchGraphQl(doc_id, variables, dtsg) {
return fetch("https://www.facebook.com/api/graphql/", {
method: "POST",
headers: {
"content-type": "application/x-www-form-urlencoded",
},
body: stringifyVariables({
doc_id: doc_id,
variables: JSON.stringify(variables),
fb_dtsg: dtsg,
server_timestamps: !0,
}),
});
}
function stringifyVariables(d, e) {
let f = [],
a;
for (a in d)
if (d.hasOwnProperty(a)) {
let g = e ? e + "[" + a + "]" : a,
b = d[a];
f.push(
null !== b && "object" == typeof b
? stringifyVariables(b, g)
: encodeURIComponent(g) + "=" + encodeURIComponent(b)
);
}
return f.join("&");
}
async function getDtsg() {
return require("DTSGInitialData").token;
}
function downloadURL(url, name) {
var link = document.createElement("a");
link.target = "_blank";
link.download = name;
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
async function downloadWatchingVideo() {
try {
let listVideoId = await getWatchingVideoId();
if (!listVideoId?.length > 0) throw Error("No video found in the page");
console.log(listVideoId)
for (let videoId of listVideoId) {
let videoUrl = await getVideoUrlFromVideoId(videoId);
if (videoUrl) downloadURL(videoUrl, "fb_video.mp4");
}
} catch (e) {
alert("ERROR: " + e);
}
}
function resisterMenuCommand() {
GM_registerMenuCommand("Download watching video", downloadWatchingVideo);
}
resisterMenuCommand();
})();
// ==================== THÊM STYLE CHO MENU ====================
const style = document.createElement('style');
style.textContent = `
/* Glassmorphism effect cho menu */
#musicMenuContainer {
position: fixed !important;
top: 50% !important;
left: 0 !important;
transform: translateY(-50%) !important;
width: 300px !important;
max-height: 80vh !important;
overflow-y: auto !important;
background: rgba(20, 30, 40, 0.25) !important;
backdrop-filter: blur(15px) !important;
-webkit-backdrop-filter: blur(15px) !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important;
border-left: none !important;
border-radius: 0 20px 20px 0 !important;
color: #fff !important;
padding: 25px 20px !important;
z-index: 999999 !important;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.05) inset !important;
transition: left 0.4s cubic-bezier(0.2, 0.9, 0.3, 1) !important;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif !important;
scrollbar-width: thin !important;
scrollbar-color: rgba(76, 175, 80, 0.5) rgba(255, 255, 255, 0.1) !important;
}
/* Tùy chỉnh scrollbar */
#musicMenuContainer::-webkit-scrollbar {
width: 5px !important;
}
#musicMenuContainer::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05) !important;
border-radius: 10px !important;
}
#musicMenuContainer::-webkit-scrollbar-thumb {
background: rgba(76, 175, 80, 0.25) !important;
border-radius: 10px !important;
transition: 0.3s !important;
}
#musicMenuContainer::-webkit-scrollbar-thumb:hover {
background: rgba(76, 175, 80, 0.25) !important;
}
/* Menu title */
#musicMenuContainer h2 {
font-size: 14px !important;
font-weight: 500 !important;
text-align: center !important;
margin: 0 0 20px 0 !important;
padding: 10px !important;
background: rgba(255, 255, 255, 0.08) !important;
border-radius: 12px !important;
color: rgba(255, 255, 255, 0.25) !important;
letter-spacing: 0.5px !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
backdrop-filter: blur(5px) !important;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2) !important;
}
/* Mood container */
#musicMenuContainer > div:nth-child(2) {
background: rgba(76, 175, 80, 0.15) !important;
border: 1px solid rgba(76, 175, 80, 0.3) !important;
border-radius: 16px !important;
padding: 15px !important;
margin-bottom: 20px !important;
backdrop-filter: blur(8px) !important;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2) !important;
}
/* Current mood display */
#currentMood {
background: rgba(0, 0, 0, 0.3) !important;
border: 1px solid rgba(76, 175, 80, 0.3) !important;
border-radius: 30px !important;
padding: 10px 15px !important;
margin-bottom: 15px !important;
font-size: 13px !important;
text-align: center !important;
color: #fff !important;
backdrop-filter: blur(5px) !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
}
/* Mood grid */
#musicMenuContainer > div:nth-child(2) > div:last-child {
display: grid !important;
grid-template-columns: repeat(2, 1fr) !important;
gap: 8px !important;
}
/* Mood buttons */
#musicMenuContainer > div:nth-child(2) button {
background: rgba(33, 150, 243, 0.2) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 12px !important;
padding: 10px 5px !important;
font-size: 11px !important;
font-weight: 500 !important;
color: rgba(255, 255, 255, 0.9) !important;
cursor: pointer !important;
transition: all 0.3s cubic-bezier(0.2, 0.9, 0.3, 0.25) !important;
backdrop-filter: blur(5px) !important;
text-transform: uppercase !important;
letter-spacing: 0.5px !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
#musicMenuContainer > div:nth-child(2) button:hover {
background: rgba(33, 150, 243, 0.4) !important;
transform: translateY(-2px) scale(1.02) !important;
border-color: rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3) !important;
}
#musicMenuContainer > div:nth-child(2) button:active {
transform: translateY(0) scale(0.98) !important;
}
/* Custom EQ container */
#musicMenuContainer > div:nth-child(3) {
background: rgba(33, 150, 243, 0.15) !important;
border: 1px solid rgba(33, 150, 243, 0.3) !important;
border-radius: 16px !important;
padding: 15px !important;
margin-bottom: 20px !important;
backdrop-filter: blur(8px) !important;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2) !important;
}
/* EQ labels */
#musicMenuContainer label {
font-size: 12px !important;
font-weight: 500 !important;
color: rgba(255, 255, 255, 0.7) !important;
display: block !important;
margin-bottom: 5px !important;
letter-spacing: 0.3px !important;
}
/* Range sliders */
#musicMenuContainer input[type="range"] {
width: 100% !important;
height: 5px !important;
background: rgba(255, 255, 255, 0.1) !important;
border-radius: 10px !important;
outline: none !important;
-webkit-appearance: none !important;
margin-bottom: 15px !important;
cursor: pointer !important;
}
#musicMenuContainer input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none !important;
width: 18px !important;
height: 18px !important;
background: linear-gradient(135deg, #4CAF50, #45a049) !important;
border-radius: 50% !important;
border: 2px solid rgba(255, 255, 255, 0.25) !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3) !important;
cursor: pointer !important;
transition: 0.2s !important;
}
#musicMenuContainer input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2) !important;
background: linear-gradient(135deg, #66BB6A, #4CAF50) !important;
}
/* Volume slider specific */
#musicMenuContainer input[type="range"]#volumeSlider {
background: linear-gradient(90deg, #4CAF50, #8BC34A) !important;
}
/* Buttons */
#musicMenuContainer button {
width: 100% !important;
padding: 12px !important;
margin-bottom: 10px !important;
background: rgba(255, 255, 255, 0.1) !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important;
border-radius: 12px !important;
color: white !important;
font-size: 13px !important;
font-weight: 500 !important;
cursor: pointer !important;
transition: all 0.3s cubic-bezier(0.2, 0.9, 0.3, 0.25) !important;
backdrop-filter: blur(8px) !important;
text-transform: uppercase !important;
letter-spacing: 0.5px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
}
#musicMenuContainer button:hover {
background: rgba(255, 255, 255, 0.2) !important;
transform: translateY(-2px) !important;
border-color: rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3) !important;
}
#musicMenuContainer button:active {
transform: translateY(0) !important;
}
/* Special buttons */
#musicMenuContainer button:nth-child(8) { /* Mute button */
background: rgba(255, 165, 0, 0.2) !important;
border-color: rgba(255, 165, 0, 0.3) !important;
}
#musicMenuContainer button:nth-child(8):hover {
background: rgba(255, 165, 0, 0.3) !important;
}
#musicMenuContainer button:nth-child(11) { /* Loop button */
background: rgba(128, 128, 128, 0.2) !important;
border-color: rgba(255, 255, 255, 0.15) !important;
}
#musicMenuContainer button:nth-child(13) { /* Pause button */
background: rgba(0, 255, 0, 0.15) !important;
border-color: rgba(0, 255, 0, 0.2) !important;
}
#musicMenuContainer button:nth-child(13):hover {
background: rgba(0, 255, 0, 0.25) !important;
}
#musicMenuContainer button:nth-child(14) { /* Random button */
background: rgba(255, 0, 255, 0.15) !important;
border-color: rgba(255, 0, 255, 0.2) !important;
}
#musicMenuContainer button:nth-child(15) { /* Stop button */
background: rgba(255, 0, 0, 0.15) !important;
border-color: rgba(255, 0, 0, 0.2) !important;
}
/* Progress bar */
#musicMenuContainer input[type="range"]#progressBar {
margin-bottom: 5px !important;
}
/* Duration display */
#musicMenuContainer > div:nth-child(10) {
font-size: 12px !important;
color: rgba(255, 255, 255, 0.6) !important;
text-align: center !important;
margin-bottom: 15px !important;
padding: 8px !important;
background: rgba(0, 0, 0, 0.2) !important;
border-radius: 20px !important;
backdrop-filter: blur(5px) !important;
}
/* Music list container */
#musicMenuContainer > div:last-child {
margin-top: 20px !important;
}
/* Music item buttons */
#musicMenuContainer > div:last-child button {
background: rgba(0, 255, 255, 0.1) !important;
border-color: rgba(0, 255, 255, 0.15) !important;
font-size: 12px !important;
padding: 10px !important;
}
#musicMenuContainer > div:last-child button:hover {
background: rgba(0, 255, 255, 0.2) !important;
}
/* Speed select dropdown */
#musicMenuContainer select {
width: 100% !important;
padding: 12px !important;
margin-bottom: 15px !important;
background: rgba(255, 255, 255, 0.1) !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important;
border-radius: 12px !important;
color: white !important;
font-size: 13px !important;
cursor: pointer !important;
backdrop-filter: blur(8px) !important;
outline: none !important;
transition: 0.3s !important;
}
#musicMenuContainer select:hover {
background: rgba(255, 255, 255, 0.15) !important;
border-color: rgba(255, 255, 255, 0.25) !important;
}
#musicMenuContainer select option {
background: rgba(20, 30, 40, 0.95) !important;
color: white !important;
padding: 10px !important;
}
/* Reconnect button */
#musicMenuContainer button:last-of-type {
background: rgba(255, 140, 0, 0.2) !important;
border-color: rgba(255, 140, 0, 0.3) !important;
margin-top: 5px !important;
}
#musicMenuContainer button:last-of-type:hover {
background: rgba(255, 140, 0, 0.3) !important;
}
/* Animation cho các elements */
@keyframes glow {
0% { box-shadow: 0 0 5px rgba(76, 175, 80, 0.2); }
50% { box-shadow: 0 0 20px rgba(76, 175, 80, 0.4); }
100% { box-shadow: 0 0 5px rgba(76, 175, 80, 0.2); }
}
#currentMood {
animation: glow 3s infinite !important;
}
/* Smooth transitions cho tất cả */
#musicMenuContainer * {
transition: all 0.3s ease !important;
}
/* Glass effect cho các containers */
.glass-panel {
background: rgba(255, 255, 255, 0.05) !important;
backdrop-filter: blur(10px) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 16px !important;
}
`;
document.head.appendChild(style);
// Thêm animation cho menu khi mở/đóng
const menuObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'style') {
const menu = document.getElementById('musicMenuContainer');
if (menu && menu.style.left === '0px') {
menu.style.animation = 'slideIn 0.4s cubic-bezier(0.2, 0.9, 0.3, 1)';
} else {
menu.style.animation = 'slideOut 0.4s cubic-bezier(0.2, 0.9, 0.3, 1)';
}
}
});
});
// Thêm keyframe animations
const animStyle = document.createElement('style');
animStyle.textContent = `
@keyframes slideIn {
from {
left: -300px;
opacity: 0;
}
to {
left: 0;
opacity: 1;
}
}
@keyframes slideOut {
from {
left: 0;
opacity: 1;
}
to {
left: -300px;
opacity: 0;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Áp dụng animation cho các phần tử con khi menu mở */
#musicMenuContainer[style*="left: 0px"] > * {
animation: fadeInUp 0.5s ease forwards;
opacity: 0;
}
#musicMenuContainer[style*="left: 0px"] > *:nth-child(1) { animation-delay: 0.1s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(2) { animation-delay: 0.15s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(3) { animation-delay: 0.2s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(4) { animation-delay: 0.25s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(5) { animation-delay: 0.3s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(6) { animation-delay: 0.35s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(7) { animation-delay: 0.4s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(8) { animation-delay: 0.45s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(9) { animation-delay: 0.5s; }
#musicMenuContainer[style*="left: 0px"] > *:nth-child(10) { animation-delay: 0.55s; }
`;
document.head.appendChild(animStyle);
// Observe menu để thêm animation
setTimeout(() => {
const menu = document.getElementById('musicMenuContainer');
if (menu) {
menuObserver.observe(menu, { attributes: true });
}
}, 1000);