// Прямое управление громкостью через Windows Audio Session API const { spawn } = require('child_process'); const fs = require('fs'); const path = require('path'); class WindowsDirectAudio { constructor() { this.musicProcess = null; this.musicVolume = 70; this.isDucked = false; this.duckVolume = 20; } play(filePath, volume = 70) { this.stop(); if (!fs.existsSync(filePath)) { console.error('[DIRECT-AUDIO] Файл не найден:', filePath); return false; } // Применяем громкость с учетом приглушения const effectiveVolume = this.isDucked ? this.duckVolume : volume; const volumeDecimal = effectiveVolume / 100; console.log('[DIRECT-AUDIO] Воспроизведение:', path.basename(filePath)); console.log('[DIRECT-AUDIO] Эффективная громкость:', effectiveVolume + '%'); // PowerShell скрипт с прямым управлением громкостью const script = ` # Загружаем Windows Media Player Add-Type -AssemblyName presentationcore $player = New-Object System.Windows.Media.MediaPlayer # Устанавливаем начальную громкость $player.Volume = ${volumeDecimal} # Открываем файл $player.Open("${filePath.replace(/\\/g, '\\\\')}") # Ждем загрузки $timeout = 0 while ($player.NaturalDuration.HasTimeSpan -eq $false -and $timeout -lt 50) { Start-Sleep -Milliseconds 100 $timeout++ } if ($player.NaturalDuration.HasTimeSpan -eq $false) { Write-Host "ERROR: Failed to load file" exit 1 } # Запускаем воспроизведение $player.Play() Write-Host "STATUS:PLAYING:${effectiveVolume}" # Файл для команд управления громкостью $controlFile = "$env:TEMP\\audio_control_$PID.txt" # Главный цикл while ($true) { # Проверяем файл с командами if (Test-Path $controlFile) { $command = Get-Content $controlFile -First 1 Remove-Item $controlFile -Force -ErrorAction SilentlyContinue if ($command -match "^VOLUME:(\d+)$") { $newVolume = [int]$matches[1] / 100 $player.Volume = $newVolume Write-Host "VOLUME_CHANGED:$($matches[1])" } elseif ($command -eq "STOP") { break } } # Проверяем завершение if ($player.Position -ge $player.NaturalDuration.TimeSpan) { Write-Host "STATUS:FINISHED" break } Start-Sleep -Milliseconds 50 } $player.Stop() $player.Close() `; this.musicProcess = spawn('powershell', [ '-NoProfile', '-WindowStyle', 'Hidden', '-Command', script ], { windowsHide: true }); this.musicVolume = volume; // Обработчики событий this.musicProcess.stdout.on('data', (data) => { const output = data.toString().trim(); console.log('[DIRECT-AUDIO]', output); }); this.musicProcess.stderr.on('data', (data) => { console.error('[DIRECT-AUDIO] Ошибка:', data.toString()); }); this.musicProcess.on('close', (code) => { console.log('[DIRECT-AUDIO] Процесс завершен:', code); this.musicProcess = null; }); return true; } stop() { if (this.musicProcess) { console.log('[DIRECT-AUDIO] Остановка воспроизведения'); // Отправляем команду остановки const controlFile = `${process.env.TEMP}\\audio_control_${this.musicProcess.pid}.txt`; try { fs.writeFileSync(controlFile, 'STOP'); } catch (err) { // Принудительная остановка this.musicProcess.kill(); } this.musicProcess = null; } } setVolume(volume) { this.musicVolume = volume; if (this.musicProcess) { const effectiveVolume = this.isDucked ? this.duckVolume : volume; const controlFile = `${process.env.TEMP}\\audio_control_${this.musicProcess.pid}.txt`; try { fs.writeFileSync(controlFile, `VOLUME:${effectiveVolume}`); console.log('[DIRECT-AUDIO] Отправлена команда изменения громкости:', effectiveVolume); } catch (err) { console.error('[DIRECT-AUDIO] Ошибка изменения громкости:', err.message); } } } duck() { console.log('[DIRECT-AUDIO] Приглушение музыки'); this.isDucked = true; this.setVolume(this.musicVolume); // Пересчитает с учетом isDucked } unduck() { console.log('[DIRECT-AUDIO] Восстановление громкости'); this.isDucked = false; this.setVolume(this.musicVolume); // Пересчитает с учетом isDucked } isPlaying() { return this.musicProcess !== null; } } module.exports = WindowsDirectAudio;