Autosave: 20260325-215756
This commit is contained in:
parent
a50e7e020c
commit
26e09bc00f
3965
Temp/index_new.php
Normal file
3965
Temp/index_new.php
Normal file
File diff suppressed because it is too large
Load Diff
106
Temp/voice_tab.html
Normal file
106
Temp/voice_tab.html
Normal 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>
|
||||
@ -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']);
|
||||
@ -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');
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
1
db/migrations/20260325_add_voice_advanced_filters.sql
Normal file
1
db/migrations/20260325_add_voice_advanced_filters.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE users ADD COLUMN voice_advanced_filters TINYINT(1) DEFAULT 1;
|
||||
14
index.php
14
index.php
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user