mirror of https://github.com/jetkvm/kvm.git
[WIP] Improvements, Bugfixes: Improve audio experience when running in HTTP mode
This commit is contained in:
parent
d311dee4c6
commit
630571da25
|
@ -244,6 +244,11 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
|||
|
||||
// Handle microphone device change
|
||||
const handleMicrophoneDeviceChange = async (deviceId: string) => {
|
||||
// Don't process device changes for HTTPS-required placeholder
|
||||
if (deviceId === 'https-required') {
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedInputDevice(deviceId);
|
||||
|
||||
// If microphone is currently active, restart it with the new device
|
||||
|
@ -402,11 +407,15 @@ export default function AudioControlPopover({ microphone }: AudioControlPopoverP
|
|||
</option>
|
||||
))}
|
||||
</select>
|
||||
{isMicrophoneActiveFromHook && (
|
||||
{isHttpsRequired ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">
|
||||
HTTPS connection required for microphone device selection
|
||||
</p>
|
||||
) : isMicrophoneActiveFromHook ? (
|
||||
<p className="text-xs text-slate-500 dark:text-slate-400">
|
||||
Changing device will restart the microphone
|
||||
</p>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{/* Speaker Selection */}
|
||||
|
|
|
@ -33,31 +33,55 @@ export function useAudioDevices(): UseAudioDevicesReturn {
|
|||
setError(null);
|
||||
|
||||
try {
|
||||
// Check if getUserMedia is available (requires HTTPS in most browsers)
|
||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||
// Set placeholder devices when HTTPS is required
|
||||
// Check if we're on HTTP (microphone requires HTTPS, but speakers can work)
|
||||
const isHttp = window.location.protocol === 'http:';
|
||||
const hasMediaDevices = !!navigator.mediaDevices;
|
||||
const hasGetUserMedia = !!navigator.mediaDevices?.getUserMedia;
|
||||
const hasEnumerateDevices = !!navigator.mediaDevices?.enumerateDevices;
|
||||
|
||||
if (isHttp || !hasMediaDevices || !hasGetUserMedia) {
|
||||
// Set placeholder devices when HTTPS is required for microphone
|
||||
setAudioInputDevices([
|
||||
{ deviceId: 'https-required', label: 'HTTPS Required for Microphone Access', kind: 'audioinput' }
|
||||
]);
|
||||
// Speakers still work on HTTP, so enumerate them normally
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const outputDevices: AudioDevice[] = [
|
||||
{ deviceId: 'default', label: 'Default Speaker', kind: 'audiooutput' }
|
||||
];
|
||||
|
||||
devices.forEach(device => {
|
||||
if (device.kind === 'audiooutput' && device.deviceId !== 'default') {
|
||||
outputDevices.push({
|
||||
deviceId: device.deviceId,
|
||||
label: device.label || `Speaker ${device.deviceId.slice(0, 8)}`,
|
||||
kind: 'audiooutput'
|
||||
// Try to enumerate speakers if possible, otherwise provide defaults
|
||||
if (hasMediaDevices && hasEnumerateDevices) {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const outputDevices: AudioDevice[] = [
|
||||
{ deviceId: 'default', label: 'Default Speaker', kind: 'audiooutput' }
|
||||
];
|
||||
|
||||
devices.forEach(device => {
|
||||
if (device.kind === 'audiooutput' && device.deviceId !== 'default') {
|
||||
outputDevices.push({
|
||||
deviceId: device.deviceId,
|
||||
label: device.label || `Speaker ${device.deviceId.slice(0, 8)}`,
|
||||
kind: 'audiooutput'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
setAudioOutputDevices(outputDevices);
|
||||
} catch {
|
||||
// Fallback to default speakers if enumeration fails
|
||||
setAudioOutputDevices([
|
||||
{ deviceId: 'default', label: 'Default Speaker', kind: 'audiooutput' },
|
||||
{ deviceId: 'system-default', label: 'System Default Audio Output', kind: 'audiooutput' }
|
||||
]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// No enumeration available, use defaults
|
||||
setAudioOutputDevices([
|
||||
{ deviceId: 'default', label: 'Default Speaker', kind: 'audiooutput' },
|
||||
{ deviceId: 'system-default', label: 'System Default Audio Output', kind: 'audiooutput' }
|
||||
]);
|
||||
}
|
||||
|
||||
setAudioOutputDevices(outputDevices);
|
||||
setSelectedInputDevice('https-required');
|
||||
throw new Error('Microphone access requires HTTPS connection. Please use HTTPS to access audio features.');
|
||||
setSelectedOutputDevice('default');
|
||||
return; // Exit gracefully without throwing error on HTTP
|
||||
}
|
||||
|
||||
// Request permissions first to get device labels
|
||||
|
@ -95,7 +119,12 @@ export function useAudioDevices(): UseAudioDevicesReturn {
|
|||
// Audio devices enumerated
|
||||
|
||||
} catch (err) {
|
||||
devError('Failed to enumerate audio devices:', err);
|
||||
// Only log errors on HTTPS where we expect full device access
|
||||
const isHttp = window.location.protocol === 'http:';
|
||||
if (!isHttp) {
|
||||
devError('Failed to enumerate audio devices:', err);
|
||||
}
|
||||
|
||||
let errorMessage = 'Failed to access audio devices';
|
||||
|
||||
if (err instanceof Error) {
|
||||
|
@ -112,7 +141,10 @@ export function useAudioDevices(): UseAudioDevicesReturn {
|
|||
}
|
||||
}
|
||||
|
||||
setError(errorMessage);
|
||||
// Only set error state on HTTPS where we expect device access to work
|
||||
if (!isHttp) {
|
||||
setError(errorMessage);
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,15 @@ export interface MicrophoneError {
|
|||
|
||||
// Helper function to check if HTTPS is required for microphone access
|
||||
export function isHttpsRequired(): boolean {
|
||||
return !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia;
|
||||
// Check if we're on HTTP (not HTTPS)
|
||||
const isHttp = window.location.protocol === 'http:';
|
||||
|
||||
// Check if media devices are available
|
||||
const hasMediaDevices = !!navigator.mediaDevices;
|
||||
const hasGetUserMedia = !!navigator.mediaDevices?.getUserMedia;
|
||||
|
||||
// HTTPS is required if we're on HTTP OR if media devices aren't available
|
||||
return isHttp || !hasMediaDevices || !hasGetUserMedia;
|
||||
}
|
||||
|
||||
export function useMicrophone() {
|
||||
|
|
Loading…
Reference in New Issue