Files
vue-pult/server/linux-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

177 lines
6.3 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.
// Специальный радио плеер для Linux с изолированным управлением громкостью
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
class LinuxRadioPlayer {
constructor() {
this.radioProcess = null;
this.isPlaying = false;
this.volume = 70;
this.currentUrl = null;
this.playerType = null;
}
detectPlayer() {
// Определяем доступный плеер в порядке приоритета
const players = [
{ name: 'cvlc', check: 'vlc --version' },
{ name: 'mplayer', check: 'mplayer -version' },
{ name: 'mpg123', check: 'mpg123 --version' },
{ name: 'ffplay', check: 'ffplay -version' }
];
for (const player of players) {
try {
require('child_process').execSync(player.check, { stdio: 'ignore' });
console.log(`[LINUX-RADIO] ✅ Найден плеер: ${player.name}`);
return player.name;
} catch (e) {
// Плеер не найден
}
}
console.log('[LINUX-RADIO] ⚠️ Не найдены рекомендуемые плееры, используем paplay');
return 'paplay';
}
play(url) {
this.stop();
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}
console.log('[LINUX-RADIO] 📻 Запуск радио:', url);
this.currentUrl = url;
this.playerType = this.detectPlayer();
let command, args;
switch (this.playerType) {
case 'cvlc':
// VLC - лучший вариант, поддерживает программное управление громкостью
command = 'cvlc';
args = [
'--intf', 'dummy',
'--no-video',
'--no-video-title-show',
'--quiet',
'--volume', Math.floor(this.volume * 2.56).toString(), // VLC использует 0-256
'--no-volume-save', // Не сохранять громкость
url
];
break;
case 'mplayer':
// MPlayer - хороший вариант с программной громкостью
command = 'mplayer';
args = [
'-quiet',
'-really-quiet',
'-nolirc',
'-novideo',
'-volume', this.volume.toString(),
'-softvol',
'-softvol-max', '100',
url
];
break;
case 'mpg123':
// mpg123 - поддерживает масштабирование громкости
command = 'mpg123';
args = [
'--quiet',
'--scale', (this.volume / 100).toString(),
url
];
break;
case 'ffplay':
// FFplay - часть FFmpeg
command = 'ffplay';
args = [
'-nodisp',
'-autoexit',
'-loglevel', 'error',
'-volume', this.volume.toString(),
url
];
break;
default:
// Fallback на paplay с громкостью
const paVolume = Math.floor((this.volume / 100) * 65536);
command = 'sh';
args = ['-c', `curl -s "${url}" | paplay --raw --format=s16le --rate=44100 --channels=2 --volume=${paVolume}`];
}
console.log(`[LINUX-RADIO] Используем ${this.playerType}:`, command, args.join(' '));
this.radioProcess = spawn(command, args, {
stdio: 'ignore', // Игнорируем весь вывод
detached: false
});
this.radioProcess.on('error', (error) => {
console.error('[LINUX-RADIO] Ошибка запуска:', error.message);
this.isPlaying = false;
});
this.radioProcess.on('exit', (code) => {
console.log('[LINUX-RADIO] Процесс завершен с кодом:', code);
this.isPlaying = false;
this.radioProcess = null;
});
this.isPlaying = true;
}
stop() {
if (this.radioProcess) {
console.log('[LINUX-RADIO] ⏹️ Остановка радио');
try {
this.radioProcess.kill('SIGTERM');
setTimeout(() => {
if (this.radioProcess) {
this.radioProcess.kill('SIGKILL');
}
}, 1000);
} catch (e) {
console.error('[LINUX-RADIO] Ошибка остановки:', e.message);
}
this.radioProcess = null;
}
this.isPlaying = false;
this.currentUrl = null;
}
setVolume(volume) {
this.volume = Math.max(0, Math.min(100, volume));
console.log('[LINUX-RADIO] 🔊 Новая громкость:', this.volume);
// Для изменения громкости на лету нужно перезапустить поток
// Это не идеально, но гарантирует отсутствие влияния на системную громкость
if (this.isPlaying && this.currentUrl) {
console.log('[LINUX-RADIO] Перезапуск потока с новой громкостью...');
const url = this.currentUrl;
this.stop();
setTimeout(() => this.play(url), 100);
}
}
getStatus() {
return {
isPlaying: this.isPlaying,
volume: this.volume,
url: this.currentUrl,
player: this.playerType
};
}
}
module.exports = { LinuxRadioPlayer };