Files
vue-pult/server/vlc-sound.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

211 lines
6.9 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.
// VLC-based sound player с поддержкой паузы и позиции
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const net = require('net');
class VLCSound {
constructor(filePath) {
this.path = path.resolve(filePath);
this.process = null;
this.isPlaying = false;
this.isPaused = false;
this.position = 0;
this.duration = 0;
this.vlcPath = this._findVLC();
this.rcInterface = null;
this.port = 8090 + Math.floor(Math.random() * 1000); // Случайный порт для RC интерфейса
console.log(`[VLC-AUDIO] Звуковой файл загружен: ${this.path}`);
console.log(`[VLC-AUDIO] VLC путь: ${this.vlcPath || 'не найден'}`);
}
_findVLC() {
const paths = [
'C:\\Program Files\\VideoLAN\\VLC\\vlc.exe',
'C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe',
path.join(process.env.PROGRAMFILES || '', 'VideoLAN\\VLC\\vlc.exe'),
path.join(process.env['PROGRAMFILES(X86)'] || '', 'VideoLAN\\VLC\\vlc.exe')
];
for (const vlcPath of paths) {
if (fs.existsSync(vlcPath)) {
return vlcPath;
}
}
return null;
}
stop() {
if (this.process) {
console.log(`[VLC-AUDIO] Останавливаем воспроизведение`);
// Сначала пробуем через RC интерфейс
this._sendCommand('quit');
setTimeout(() => {
if (this.process) {
this.process.kill();
}
}, 500);
this.process = null;
this.isPlaying = false;
this.isPaused = false;
this.position = 0;
}
return this;
}
play(onStart = null, onEnd = null, startPosition = 0) {
if (!this.vlcPath) {
console.error('[VLC-AUDIO] VLC не найден! Используйте обычный плеер.');
return this;
}
console.log(`[VLC-AUDIO] Воспроизведение: ${this.path} с позиции ${startPosition}с`);
// Останавливаем предыдущее воспроизведение
this.stop();
// Проверяем файл
if (!fs.existsSync(this.path)) {
console.error(`[VLC-AUDIO] Файл не найден: ${this.path}`);
return this;
}
// Запускаем VLC с RC интерфейсом
const args = [
'--intf', 'rc',
'--rc-host', `localhost:${this.port}`,
'--no-video',
'--play-and-exit',
this.path
];
if (startPosition > 0) {
args.push('--start-time', startPosition.toString());
}
this.process = spawn(this.vlcPath, args, {
stdio: 'pipe',
windowsHide: true
});
this.isPlaying = true;
this.isPaused = false;
// Подключаемся к RC интерфейсу через небольшую задержку
setTimeout(() => {
this._connectRC();
}, 1000);
if (onStart) {
setTimeout(onStart, 500);
}
this.process.on('close', (code) => {
console.log(`[VLC-AUDIO] Воспроизведение завершено`);
this.isPlaying = false;
this.isPaused = false;
this.process = null;
if (onEnd) onEnd();
});
this.process.on('error', (error) => {
console.error(`[VLC-AUDIO] Ошибка процесса:`, error.message);
this.isPlaying = false;
this.process = null;
});
return this;
}
pause() {
if (this.isPlaying && !this.isPaused) {
console.log('[VLC-AUDIO] Пауза');
this._sendCommand('pause');
this.isPaused = true;
this.isPlaying = false;
// Получаем текущую позицию
this._sendCommand('get_time', (response) => {
const match = response.match(/(\d+)/);
if (match) {
this.position = parseInt(match[1]);
console.log('[VLC-AUDIO] Позиция сохранена:', this.position, 'сек');
}
});
}
return this;
}
resume() {
if (this.isPaused && this.process) {
console.log('[VLC-AUDIO] Возобновление');
this._sendCommand('pause'); // В VLC pause переключает состояние
this.isPaused = false;
this.isPlaying = true;
}
return this;
}
setVolume(volume) {
// VLC принимает громкость от 0 до 256 (256 = 100%)
const vlcVolume = Math.floor((volume / 100) * 256);
this._sendCommand(`volume ${vlcVolume}`);
console.log('[VLC-AUDIO] Громкость установлена:', volume + '%');
return this;
}
getPosition(callback) {
this._sendCommand('get_time', (response) => {
const match = response.match(/(\d+)/);
if (match && callback) {
callback(parseInt(match[1]));
}
});
}
_connectRC() {
this.rcInterface = new net.Socket();
this.rcInterface.connect(this.port, 'localhost', () => {
console.log('[VLC-AUDIO] Подключен к RC интерфейсу');
});
this.rcInterface.on('error', (err) => {
console.log('[VLC-AUDIO] RC интерфейс недоступен:', err.message);
});
}
_sendCommand(command, callback) {
if (this.rcInterface && !this.rcInterface.destroyed) {
this.rcInterface.write(command + '\n');
if (callback) {
this.rcInterface.once('data', (data) => {
callback(data.toString());
});
}
}
}
}
// Фабрика для выбора правильного плеера
function createSound(filePath) {
const vlcSound = new VLCSound(filePath);
// Если VLC найден, используем его
if (vlcSound.vlcPath) {
return vlcSound;
}
// Иначе возвращаем обычный плеер
console.log('[AUDIO] VLC не найден, используем стандартный плеер');
const StandardSound = require('./node-aplay');
return new StandardSound(filePath);
}
module.exports = createSound;
module.exports.VLCSound = VLCSound;