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

222 lines
7.0 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.
// Радио плеер через Node.js с поддержкой HTTP потоков
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const http = require('http');
const https = require('https');
class RadioStreamPlayer {
constructor() {
this.isPlaying = false;
this.volume = 70;
this.currentUrl = null;
this.ffplayProcess = null;
this.vlcProcess = null;
this.mpvProcess = null;
}
play(url) {
this.stop();
// Добавляем протокол если его нет
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}
console.log('[RADIO] 🎵 Запуск радио потока:', url);
this.currentUrl = url;
// Пробуем разные плееры в порядке предпочтения
this._tryMpv(url) || this._tryVlc(url) || this._tryFfplay(url) || this._tryPowerShell(url);
}
_tryMpv(url) {
try {
const mpvPath = path.join(__dirname, 'tools', 'mpv.exe');
if (!fs.existsSync(mpvPath)) {
console.log('[RADIO] MPV не найден');
return false;
}
console.log('[RADIO] Запуск через MPV');
this.mpvProcess = spawn(mpvPath, [
'--no-video',
'--volume=' + this.volume,
'--no-terminal',
url
]);
this.mpvProcess.on('error', (err) => {
console.error('[RADIO] MPV ошибка:', err.message);
this.isPlaying = false;
});
this.mpvProcess.on('exit', (code) => {
console.log('[RADIO] MPV завершен с кодом:', code);
this.isPlaying = false;
});
this.isPlaying = true;
return true;
} catch (err) {
console.error('[RADIO] Ошибка MPV:', err.message);
return false;
}
}
_tryVlc(url) {
try {
const vlcPaths = [
path.join(__dirname, 'tools', 'vlc.exe'),
'C:\\Program Files\\VideoLAN\\VLC\\vlc.exe',
'C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe'
];
let vlcPath = null;
for (const p of vlcPaths) {
if (fs.existsSync(p)) {
vlcPath = p;
break;
}
}
if (!vlcPath) {
console.log('[RADIO] VLC не найден');
return false;
}
console.log('[RADIO] Запуск через VLC');
this.vlcProcess = spawn(vlcPath, [
'--intf', 'dummy',
'--no-video',
'--volume', Math.floor(this.volume * 2.56).toString(),
url
]);
this.vlcProcess.on('error', (err) => {
console.error('[RADIO] VLC ошибка:', err.message);
this.isPlaying = false;
});
this.vlcProcess.on('exit', (code) => {
console.log('[RADIO] VLC завершен с кодом:', code);
this.isPlaying = false;
});
this.isPlaying = true;
return true;
} catch (err) {
console.error('[RADIO] Ошибка VLC:', err.message);
return false;
}
}
_tryFfplay(url) {
try {
const ffplayPath = path.join(__dirname, 'tools', 'ffplay.exe');
if (!fs.existsSync(ffplayPath)) {
console.log('[RADIO] ffplay не найден');
return false;
}
console.log('[RADIO] Запуск через ffplay');
this.ffplayProcess = spawn(ffplayPath, [
'-nodisp',
'-volume', this.volume.toString(),
'-autoexit',
url
]);
this.ffplayProcess.on('error', (err) => {
console.error('[RADIO] ffplay ошибка:', err.message);
this.isPlaying = false;
});
this.ffplayProcess.on('exit', (code) => {
console.log('[RADIO] ffplay завершен с кодом:', code);
this.isPlaying = false;
});
this.isPlaying = true;
return true;
} catch (err) {
console.error('[RADIO] Ошибка ffplay:', err.message);
return false;
}
}
_tryPowerShell(url) {
try {
console.log('[RADIO] Запуск через PowerShell и Windows Media Player');
const script = `
Add-Type -AssemblyName presentationCore
$player = New-Object System.Windows.Media.MediaPlayer
$player.Volume = ${this.volume / 100}
$player.Open([Uri]"${url}")
$player.Play()
# Держим процесс активным
while ($player.HasAudio -or $player.NaturalDuration.TimeSpan.TotalSeconds -eq 0) {
Start-Sleep -Milliseconds 100
}
`;
spawn('powershell', ['-Command', script]);
this.isPlaying = true;
return true;
} catch (err) {
console.error('[RADIO] Ошибка PowerShell:', err.message);
return false;
}
}
stop() {
console.log('[RADIO] ⏹️ Остановка радио');
if (this.mpvProcess) {
this.mpvProcess.kill();
this.mpvProcess = null;
}
if (this.vlcProcess) {
this.vlcProcess.kill();
this.vlcProcess = null;
}
if (this.ffplayProcess) {
this.ffplayProcess.kill();
this.ffplayProcess = null;
}
// Убиваем любые оставшиеся процессы
spawn('taskkill', ['/F', '/IM', 'mpv.exe'], { stdio: 'ignore' });
spawn('taskkill', ['/F', '/IM', 'vlc.exe'], { stdio: 'ignore' });
spawn('taskkill', ['/F', '/IM', 'ffplay.exe'], { stdio: 'ignore' });
this.isPlaying = false;
this.currentUrl = null;
}
setVolume(volume) {
this.volume = Math.max(0, Math.min(100, volume));
console.log('[RADIO] 🔊 Установка громкости:', this.volume);
// Для изменения громкости нужно перезапустить
if (this.isPlaying && this.currentUrl) {
const url = this.currentUrl;
this.stop();
setTimeout(() => this.play(url), 500);
}
}
getStatus() {
return {
isPlaying: this.isPlaying,
currentUrl: this.currentUrl,
volume: this.volume
};
}
}
module.exports = RadioStreamPlayer;