Autosave: 20260325-215756

This commit is contained in:
Flatlogic Bot 2026-03-25 21:57:57 +00:00
parent a50e7e020c
commit 26e09bc00f
7 changed files with 4125 additions and 32 deletions

3965
Temp/index_new.php Normal file

File diff suppressed because it is too large Load Diff

106
Temp/voice_tab.html Normal file
View File

@ -0,0 +1,106 @@
<!-- Voice Tab -->
<div class="tab-pane fade" id="settings-voice" role="tabpanel">
<h5 class="mb-4 fw-bold text-uppercase" style="font-size: 0.8em; color: var(--text-muted);">Paramètres de voix</h5>
<div class="row mb-4">
<div class="col-md-6 mb-3">
<label class="form-label text-uppercase fw-bold mb-2" style="font-size: 0.7em; color: var(--text-muted);">Périphérique d'entrée</label>
<select name="voice_input_device" id="voice_input_device" class="form-select bg-dark text-white border-0">
<option value="default">Défaut</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label text-uppercase fw-bold mb-2" style="font-size: 0.7em; color: var(--text-muted);">Périphérique de sortie</label>
<select name="voice_output_device" id="voice_output_device" class="form-select bg-dark text-white border-0">
<option value="default">Défaut</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label class="form-label text-uppercase fw-bold mb-2" style="font-size: 0.7em; color: var(--text-muted);">Volume d'entrée</label>
<input type="range" name="voice_input_volume" id="voice_input_volume" class="form-range" min="0" max="1" step="0.01" value="1.0">
<script>document.getElementById('voice_input_volume').value = localStorage.getItem('voice_input_volume') || 1.0;</script>
</div>
<div class="col-md-6 mb-3">
<label class="form-label text-uppercase fw-bold mb-2" style="font-size: 0.7em; color: var(--text-muted);">Volume de sortie</label>
<input type="range" name="voice_output_volume" id="voice_output_volume" class="form-range" min="0" max="2" step="0.01" value="1.0">
<script>document.getElementById('voice_output_volume').value = localStorage.getItem('voice_output_volume') || 1.0;</script>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" name="voice_echo_cancellation" id="echo-cancellation-switch" value="1" <?php echo ($user['voice_echo_cancellation'] ?? 1) ? 'checked' : ''; ?>>
<label class="form-check-label" for="echo-cancellation-switch">Annulation de l'écho</label>
</div>
<div class="form-text text-muted small mb-3">Réduit l'écho causé par vos haut-parleurs captés par votre micro.</div>
</div>
<div class="col-md-6">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" name="voice_noise_suppression" id="noise-suppression-switch" value="1" <?php echo ($user['voice_noise_suppression'] ?? 1) ? 'checked' : ''; ?>>
<label class="form-check-label" for="noise-suppression-switch">Suppression du bruit</label>
</div>
<div class="form-text text-muted small mb-3">Filtre les bruits de fond comme les ventilateurs ou les clics de clavier.</div>
</div>
<div class="col-md-12">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" name="voice_advanced_filters" id="advanced-filters-switch" value="1" <?php echo ($user['voice_advanced_filters'] ?? 1) ? 'checked' : ''; ?>>
<label class="form-check-label" for="advanced-filters-switch">Filtres avancés (Highpass & AGC)</label>
</div>
<div class="form-text text-muted small mb-3">Active des filtres supplémentaires (passe-haut, gain auto optimisé) pour une qualité vocale supérieure sur Chrome.</div>
</div>
</div>
<div class="p-3 rounded mb-4 settings-section-bg">
<label class="form-label text-uppercase fw-bold mb-3" style="font-size: 0.7em; color: var(--text-muted);">Mode d'entrée</label>
<div class="d-flex gap-3 mb-4">
<div class="form-check custom-radio-card flex-grow-1">
<input class="form-check-input d-none" type="radio" name="voice_mode" id="voice-mode-vox" value="vox" <?php echo ($user['voice_mode'] ?? 'vox') == 'vox' ? 'checked' : ''; ?> onchange="togglePTTParamètres('vox')">
<label class="form-check-label w-100 p-3 rounded border border-secondary text-center cursor-pointer" for="voice-mode-vox" style="cursor: pointer;">
<i class="fa-solid fa-microphone mb-2 d-block"></i>
Activité vocale
</label>
</div>
<div class="form-check custom-radio-card flex-grow-1">
<input class="form-check-input d-none" type="radio" name="voice_mode" id="voice-mode-ptt" value="ptt" <?php echo ($user['voice_mode'] ?? 'vox') == 'ptt' ? 'checked' : ''; ?> onchange="togglePTTParamètres('ptt')">
<label class="form-check-label w-100 p-3 rounded border border-secondary text-center cursor-pointer" for="voice-mode-ptt" style="cursor: pointer;">
<i class="fa-solid fa-keyboard mb-2 d-block"></i>
Appuyer pour parler
</label>
</div>
</div>
<div id="ptt-settings-container" style="<?php echo ($user['voice_mode'] ?? 'vox') == 'ptt' ? '' : 'display: none;'; ?>">
<div class="mb-3">
<label class="form-label small fw-bold">Raccourci clavier</label>
<input type="text" name="voice_ptt_key" id="voice_ptt_key_input" class="form-control bg-dark text-white border-0" value="<?php echo htmlspecialchars($user['voice_ptt_key'] ?? 'v'); ?>" placeholder="Click and press a key..." readonly style="cursor: pointer; caret-color: transparent;">
<div class="form-text text-muted" style="font-size: 0.8em;">Click the box and press any key to set your PTT shortcut.</div>
</div>
</div>
<div id="vox-settings-container" style="<?php echo ($user['voice_mode'] ?? 'vox') == 'vox' ? '' : 'display: none;'; ?>">
<div class="mb-3">
<label class="form-label small fw-bold">Input Sensitivity</label>
<div class="voice-meter-container mb-2" style="height: 8px; background: var(--bg-servers); border-radius: 4px; overflow: hidden; position: relative;">
<div id="voice-meter-bar" style="height: 100%; width: 0%; background: #23a559; transition: width 0.1s;"></div>
<div id="voice-meter-threshold" style="position: absolute; top: 0; bottom: 0; width: 2px; background: #f23f43; z-index: 2;"></div>
</div>
<input type="range" name="voice_vox_threshold" id="vox_threshold_input" class="form-range" min="0" max="1" step="0.01" value="<?php echo $user['voice_vox_threshold'] ?? 0.1; ?>">
<div class="d-flex justify-content-between small text-muted mt-1">
<span>Sensitive</span>
<span>Loud Only</span>
</div>
</div>
</div>
</div>
<div class="p-3 rounded border border-info border-opacity-25" style="background-color: rgba(0, 168, 252, 0.05);">
<div class="d-flex">
<i class="fa-solid fa-circle-info text-info me-3 mt-1"></i>
<div>
<div class="fw-bold text-info small mb-1">Microphone Access</div>
<div class="text-muted small">Voice channels require microphone permission. If you don't hear anything, check your browser's site settings.</div>
</div>
</div>
</div>
</div>

View File

@ -28,10 +28,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$voice_vox_threshold = isset($_POST['voice_vox_threshold']) ? (float)$_POST['voice_vox_threshold'] : ($user['voice_vox_threshold'] ?? 0.1);
$voice_echo_cancellation = isset($_POST['voice_echo_cancellation']) ? (int)$_POST['voice_echo_cancellation'] : ($user['voice_echo_cancellation'] ?? 1);
$voice_noise_suppression = isset($_POST['voice_noise_suppression']) ? (int)$_POST['voice_noise_suppression'] : ($user['voice_noise_suppression'] ?? 1);
$voice_advanced_filters = isset($_POST['voice_advanced_filters']) ? (int)$_POST['voice_advanced_filters'] : ($user['voice_advanced_filters'] ?? 1);
try {
$stmt = db()->prepare("UPDATE users SET display_name = ?, avatar_url = ?, dnd_mode = ?, sound_notifications = ?, theme = ?, voice_mode = ?, voice_ptt_key = ?, voice_vox_threshold = ?, voice_echo_cancellation = ?, voice_noise_suppression = ? WHERE id = ?");
$stmt->execute([$display_name, $avatar_url, $dnd_mode, $sound_notifications, $theme, $voice_mode, $voice_ptt_key, $voice_vox_threshold, $voice_echo_cancellation, $voice_noise_suppression, $user['id']]);
$stmt = db()->prepare("UPDATE users SET display_name = ?, avatar_url = ?, dnd_mode = ?, sound_notifications = ?, theme = ?, voice_mode = ?, voice_ptt_key = ?, voice_vox_threshold = ?, voice_echo_cancellation = ?, voice_noise_suppression = ?, voice_advanced_filters = ? WHERE id = ?");
$stmt->execute([$display_name, $avatar_url, $dnd_mode, $sound_notifications, $theme, $voice_mode, $voice_ptt_key, $voice_vox_threshold, $voice_echo_cancellation, $voice_noise_suppression, $voice_advanced_filters, $user['id']]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
@ -40,4 +41,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
echo json_encode(['success' => false, 'error' => 'Invalid request']);
echo json_encode(['success' => false, 'error' => 'Invalid request']);

View File

@ -480,7 +480,7 @@ document.addEventListener('DOMContentLoaded', () => {
let voiceHandler;
if (typeof VoiceChannel !== 'undefined') {
voiceHandler = new VoiceChannel(null, window.voiceSettings);
voiceHandler = new VoiceChannel(null, window.voiceParamètres);
window.voiceHandler = voiceHandler;
console.log('VoiceHandler initialized');

View File

@ -12,7 +12,8 @@ class VoiceChannel {
inputVolume: 1.0,
outputVolume: 1.0,
echoCancellation: true,
noiseSuppression: true
noiseSuppression: true,
advancedFilters: true
};
console.log('VoiceChannel constructor called with settings:', this.settings);
this.localStream = null;
@ -69,6 +70,36 @@ class VoiceChannel {
}, 200);
}
getAudioConstraints() {
const useAdvanced = this.settings.advancedFilters !== false;
const constraints = {
echoCancellation: { ideal: this.settings.echoCancellation },
noiseSuppression: { ideal: this.settings.noiseSuppression },
autoGainControl: { ideal: useAdvanced },
// Chromium-specific flags
googEchoCancellation: { ideal: this.settings.echoCancellation },
googAutoGainControl: { ideal: useAdvanced },
googNoiseSuppression: { ideal: this.settings.noiseSuppression },
googHighpassFilter: { ideal: useAdvanced },
googTypingNoiseDetection: { ideal: true },
googAudioMirroring: { ideal: false },
googNoiseReduction: { ideal: this.settings.noiseSuppression },
googAutoGainControl2: { ideal: useAdvanced },
googAudioMirroring: { ideal: false },
// Standard constraints
channelCount: { ideal: 1 },
sampleRate: { ideal: 48000 },
sampleSize: { ideal: 16 }
};
if (this.settings.inputDevice !== 'default') {
constraints.deviceId = { exact: this.settings.inputDevice };
}
return constraints;
}
setupPTTListeners() {
window.addEventListener('keydown', (e) => {
// Ignore if in input field
@ -197,16 +228,9 @@ class VoiceChannel {
try {
console.log('Requesting microphone access with device:', this.settings.inputDevice);
const constraints = {
audio: {
echoCancellation: this.settings.echoCancellation,
noiseSuppression: this.settings.noiseSuppression,
autoGainControl: true
},
audio: this.getAudioConstraints(),
video: false
};
if (this.settings.inputDevice !== 'default') {
constraints.audio.deviceId = { exact: this.settings.inputDevice };
}
this.localStream = await navigator.mediaDevices.getUserMedia(constraints);
console.log('Microphone access granted');
this.setMute(false); // Join unmuted by default (self-mute off)
@ -685,16 +709,9 @@ class VoiceChannel {
this.settings.inputDevice = deviceId;
if (this.currentChannelId && this.localStream) {
const constraints = {
audio: {
echoCancellation: this.settings.echoCancellation,
noiseSuppression: this.settings.noiseSuppression,
autoGainControl: true
},
audio: this.getAudioConstraints(),
video: false
};
if (deviceId !== 'default') {
constraints.audio.deviceId = { exact: deviceId };
}
const newStream = await navigator.mediaDevices.getUserMedia(constraints);
const newTrack = newStream.getAudioTracks()[0];
@ -721,18 +738,11 @@ class VoiceChannel {
async updateAudioConstraints() {
if (this.currentChannelId && this.localStream) {
console.log('Updating audio constraints:', this.settings.echoCancellation, this.settings.noiseSuppression);
console.log('Updating audio constraints:', this.settings.echoCancellation, this.settings.noiseSuppression, this.settings.advancedFilters);
const constraints = {
audio: {
echoCancellation: this.settings.echoCancellation,
noiseSuppression: this.settings.noiseSuppression,
autoGainControl: true
},
audio: this.getAudioConstraints(),
video: false
};
if (this.settings.inputDevice !== 'default') {
constraints.audio.deviceId = { exact: this.settings.inputDevice };
}
try {
const newStream = await navigator.mediaDevices.getUserMedia(constraints);
const newTrack = newStream.getAudioTracks()[0];

View File

@ -0,0 +1 @@
ALTER TABLE users ADD COLUMN voice_advanced_filters TINYINT(1) DEFAULT 1;

View File

@ -482,6 +482,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
voxThreshold: <?php echo $user['voice_vox_threshold'] ?? 0.1; ?>,
echoCancellation: <?php echo ($user['voice_echo_cancellation'] ?? 1) ? 'true' : 'false'; ?>,
noiseSuppression: <?php echo ($user['voice_noise_suppression'] ?? 1) ? 'true' : 'false'; ?>,
advancedFilters: <?php echo ($user['voice_advanced_filters'] ?? 1) ? 'true' : 'false'; ?>,
inputDevice: localStorage.getItem('voice_input_device') || 'default',
outputDevice: localStorage.getItem('voice_output_device') || 'default',
inputVolume: parseFloat(localStorage.getItem('voice_input_volume') || 1.0),
@ -1861,6 +1862,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
</div>
<!-- Voice Tab -->
<!-- Voice Tab -->
<div class="tab-pane fade" id="settings-voice" role="tabpanel">
<h5 class="mb-4 fw-bold text-uppercase" style="font-size: 0.8em; color: var(--text-muted);">Paramètres de voix</h5>
@ -1904,6 +1906,13 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
</div>
<div class="form-text text-muted small mb-3">Filtre les bruits de fond comme les ventilateurs ou les clics de clavier.</div>
</div>
<div class="col-md-12">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" name="voice_advanced_filters" id="advanced-filters-switch" value="1" <?php echo ($user['voice_advanced_filters'] ?? 1) ? 'checked' : ''; ?>>
<label class="form-check-label" for="advanced-filters-switch">Filtres avancés (Highpass & AGC)</label>
</div>
<div class="form-text text-muted small mb-3">Active des filtres supplémentaires (passe-haut, gain auto optimisé) pour une qualité vocale supérieure sur Chrome.</div>
</div>
</div>
<div class="p-3 rounded mb-4 settings-section-bg">
@ -1959,8 +1968,6 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
</div>
</div>
</div>
<!-- Whispers Tab -->
<div class="tab-pane fade" id="settings-whispers" role="tabpanel">
<h5 class="mb-4 fw-bold text-uppercase" style="font-size: 0.8em; color: var(--text-muted);">Whisper Configurations</h5>
@ -2182,11 +2189,13 @@ async function handleSaveUserParamètres(btn) {
const soundNotifications = document.getElementById('sound-notifications-switch')?.checked ? '1' : '0';
const echoCancellation = document.getElementById('echo-cancellation-switch')?.checked ? '1' : '0';
const noiseSuppression = document.getElementById('noise-suppression-switch')?.checked ? '1' : '0';
const advancedFilters = document.getElementById('advanced-filters-switch')?.checked ? '1' : '0';
formData.set('dnd_mode', dndMode);
formData.set('sound_notifications', soundNotifications);
formData.set('voice_echo_cancellation', echoCancellation);
formData.set('voice_noise_suppression', noiseSuppression);
formData.set('voice_advanced_filters', advancedFilters);
// Explicitly get theme and voice_mode to ensure they are captured
const themeInput = form.querySelector('input[name="theme"]:checked');
@ -2221,6 +2230,7 @@ async function handleSaveUserParamètres(btn) {
window.voiceHandler.settings.voxThreshold = voxThreshold;
window.voiceHandler.settings.echoCancellation = echoCancellation === '1';
window.voiceHandler.settings.noiseSuppression = noiseSuppression === '1';
window.voiceHandler.settings.advancedFilters = advancedFilters === '1';
// New settings
const inputDevice = document.getElementById('voice_input_device')?.value;