Files
vue-pult/server/improved-radio-player.js
sasha 3e90269b0b Initial commit: Vue.js тир управления система
- Клиентская часть Vue 3 + Vite
- Серверная часть Node.js + WebSocket
- Система авторизации и смен
- Управление игровыми портами
- Поддержка тем (светлая/темная)
- Адаптивный дизайн

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 12:24:22 +03:00

218 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Улучшенный радио плеер с точным управлением громкостью процесса
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
class ImprovedRadioPlayer {
constructor() {
this.radioProcess = null;
this.isPlaying = false;
this.volume = 70;
this.currentUrl = null;
this.playerPid = null;
this.volumeControlInterval = null;
}
play(url) {
this.stop();
// Добавляем протокол если его нет
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}
console.log('[RADIO] 📻 Запуск радио:', url);
this.currentUrl = url;
// Улучшенный PowerShell скрипт с контролем громкости
const script = `
# Включаем отображение ошибок
$ErrorActionPreference = "Continue"
# Создаем Windows Media Player
Add-Type -AssemblyName presentationCore
$player = New-Object System.Windows.Media.MediaPlayer
# Выводим PID для контроля громкости
Write-Host "PID:$PID"
# Открываем поток
try {
$player.Open([System.Uri]"${url}")
$player.Volume = ${this.volume / 100}
# Ждем загрузки потока
Start-Sleep -Seconds 2
# Начинаем воспроизведение
$player.Play()
Write-Host "STATUS:PLAYING"
# Держим процесс активным и проверяем громкость
while ($true) {
# Проверяем файл с командами громкости
$cmdFile = "$env:TEMP\\radio_volume_$PID.txt"
if (Test-Path $cmdFile) {
$newVolume = Get-Content $cmdFile -ErrorAction SilentlyContinue
if ($newVolume) {
$player.Volume = [double]$newVolume / 100
Write-Host "VOLUME:$newVolume"
Remove-Item $cmdFile -Force -ErrorAction SilentlyContinue
}
}
Start-Sleep -Milliseconds 500
}
} catch {
Write-Host "ERROR:$($_.Exception.Message)"
}`;
// Сохраняем скрипт
const scriptPath = path.join(__dirname, 'temp_radio.ps1');
fs.writeFileSync(scriptPath, script);
// Запускаем PowerShell с более чистыми параметрами
this.radioProcess = spawn('powershell', [
'-ExecutionPolicy', 'Bypass',
'-NoProfile',
'-WindowStyle', 'Hidden',
'-File', scriptPath
], {
windowsHide: true
});
this.radioProcess.stdout.on('data', (data) => {
const output = data.toString().trim();
console.log('[RADIO] Вывод:', output);
// Извлекаем PID
const pidMatch = output.match(/PID:(\d+)/);
if (pidMatch) {
this.playerPid = pidMatch[1];
console.log('[RADIO] PID процесса:', this.playerPid);
// Применяем громкость через NirCmd если доступен
this._applyNircmdVolume();
}
// Проверяем статус
if (output.includes('STATUS:PLAYING')) {
console.log('[RADIO] ✅ Радио запущено успешно');
}
});
this.radioProcess.stderr.on('data', (data) => {
console.error('[RADIO] Ошибка:', data.toString());
});
this.radioProcess.on('exit', (code) => {
console.log('[RADIO] Процесс завершен с кодом:', code);
this.isPlaying = false;
this._cleanup();
});
this.isPlaying = true;
// Запускаем периодическое применение громкости
this._startVolumeControl();
}
stop() {
if (this.radioProcess) {
console.log('[RADIO] ⏹️ Остановка радио');
// Останавливаем контроль громкости
if (this.volumeControlInterval) {
clearInterval(this.volumeControlInterval);
this.volumeControlInterval = null;
}
this.radioProcess.kill();
this.radioProcess = null;
}
this._cleanup();
this.isPlaying = false;
this.currentUrl = null;
this.playerPid = null;
}
setVolume(volume) {
this.volume = Math.max(0, Math.min(100, volume));
console.log('[RADIO] 🔊 Установка громкости:', this.volume);
if (this.isPlaying) {
// Метод 1: Через NirCmd (самый надежный)
this._applyNircmdVolume();
// Метод 2: Через файл команд для PowerShell
if (this.playerPid) {
const cmdFile = path.join(process.env.TEMP || '', `radio_volume_${this.playerPid}.txt`);
fs.writeFileSync(cmdFile, this.volume.toString());
}
}
}
_applyNircmdVolume() {
const nircmdPath = path.join(__dirname, 'tools', 'nircmd.exe');
if (fs.existsSync(nircmdPath)) {
if (this.playerPid) {
// Метод 1: Устанавливаем громкость для конкретного PID
spawn(nircmdPath, [
'setappvolume',
`/${this.playerPid}`,
(this.volume / 100).toString()
], {
stdio: 'ignore',
windowsHide: true
});
// Метод 2: Дополнительно для всех PowerShell процессов
spawn(nircmdPath, [
'setappvolume',
'powershell.exe',
(this.volume / 100).toString()
], {
stdio: 'ignore',
windowsHide: true
});
console.log('[RADIO] ✅ Громкость установлена через NirCmd');
}
} else {
console.log('[RADIO] ⚠️ NirCmd не найден! Установите его для управления громкостью.');
console.log('[RADIO] 📁 Путь для установки:', nircmdPath);
}
}
_startVolumeControl() {
// Применяем громкость каждые 2 секунды для надежности
this.volumeControlInterval = setInterval(() => {
if (this.isPlaying && this.playerPid) {
this._applyNircmdVolume();
}
}, 2000);
}
_cleanup() {
// Удаляем временные файлы
try {
const scriptPath = path.join(__dirname, 'temp_radio.ps1');
if (fs.existsSync(scriptPath)) {
fs.unlinkSync(scriptPath);
}
// Удаляем файл команд громкости
if (this.playerPid) {
const cmdFile = path.join(process.env.TEMP || '', `radio_volume_${this.playerPid}.txt`);
if (fs.existsSync(cmdFile)) {
fs.unlinkSync(cmdFile);
}
}
} catch (e) {
// Игнорируем ошибки очистки
}
}
}
module.exports = ImprovedRadioPlayer;