mirror of
https://github.com/R0m1k3/Regisflow.git
synced 2026-10-11 17:29:48 +02:00
Improve camera functionality and identify potential issues in production
Adds camera diagnostics and improves video constraints for production use in useSimpleCamera.tsx and cameraDebug.ts. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 4b008663-bd72-492b-b0b6-fa252367e730 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0715008c-7244-40f4-befc-26c014852236/4b008663-bd72-492b-b0b6-fa252367e730/tRJufBX
This commit is contained in:
1 parent
a939b1068d
commit
c68e72fa2a
2 files changed
+168
-13
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { useState, useRef, useCallback } from 'react';
|
||||
import { PhotoType } from '@/types/sale';
|
||||
import { getCameraCapabilities, logCameraCapabilities } from '@/utils/cameraDebug';
|
||||
|
||||
export function useSimpleCamera() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
@@ -13,9 +14,14 @@ export function useSimpleCamera() {
|
||||
const startCamera = useCallback(async (photoType: PhotoType): Promise<void> => {
|
||||
console.log('=== SIMPLE CAMERA START ===');
|
||||
|
||||
// Diagnostic complet des capacités caméra
|
||||
const capabilities = await getCameraCapabilities();
|
||||
logCameraCapabilities(capabilities);
|
||||
|
||||
try {
|
||||
// Nettoyer le stream précédent s'il existe
|
||||
if (stream) {
|
||||
console.log('Cleaning up previous stream...');
|
||||
stream.getTracks().forEach(track => track.stop());
|
||||
setStream(null);
|
||||
}
|
||||
@@ -25,6 +31,11 @@ export function useSimpleCamera() {
|
||||
throw new Error('Votre navigateur ne supporte pas l\'accès à la caméra. Utilisez un navigateur moderne comme Chrome, Firefox ou Safari.');
|
||||
}
|
||||
|
||||
// HTTPS check for production
|
||||
if (location.protocol !== 'https:' && location.hostname !== 'localhost' && location.hostname !== '127.0.0.1') {
|
||||
console.warn('Camera access may be restricted on non-HTTPS connections');
|
||||
}
|
||||
|
||||
// État initial
|
||||
setCurrentPhotoType(photoType);
|
||||
setIsOpen(true);
|
||||
@@ -32,26 +43,40 @@ export function useSimpleCamera() {
|
||||
let mediaStream: MediaStream;
|
||||
|
||||
try {
|
||||
// Essayer d'abord avec des contraintes simples
|
||||
console.log('Trying basic video constraints...');
|
||||
// Essayer d'abord avec des contraintes optimisées pour production
|
||||
console.log('Trying production-optimized video constraints...');
|
||||
mediaStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
width: { ideal: 1280, max: 1920 },
|
||||
height: { ideal: 720, max: 1080 }
|
||||
width: { ideal: 1280, min: 640, max: 1920 },
|
||||
height: { ideal: 720, min: 480, max: 1080 },
|
||||
facingMode: 'environment' // Préférer la caméra arrière
|
||||
}
|
||||
});
|
||||
console.log('Basic video constraints successful');
|
||||
console.log('Production video constraints successful');
|
||||
} catch (basicError) {
|
||||
console.warn('Basic constraints failed, trying minimal video:', basicError);
|
||||
console.warn('Production constraints failed, trying user-facing camera:', basicError);
|
||||
|
||||
try {
|
||||
// Fallback avec caméra avant
|
||||
mediaStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: {
|
||||
width: { ideal: 1280, min: 640 },
|
||||
height: { ideal: 720, min: 480 },
|
||||
facingMode: 'user'
|
||||
}
|
||||
});
|
||||
console.log('User-facing camera successful');
|
||||
} catch (userError) {
|
||||
console.warn('User-facing camera failed, trying basic constraints:', userError);
|
||||
|
||||
try {
|
||||
// Fallback ultra-simple
|
||||
mediaStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true
|
||||
});
|
||||
console.log('Minimal video constraints successful');
|
||||
console.log('Basic video constraints successful');
|
||||
} catch (minimalError) {
|
||||
console.error('All camera access failed:', minimalError);
|
||||
console.error('All camera access attempts failed:', minimalError);
|
||||
|
||||
// Fermer la modal en cas d'erreur
|
||||
setIsOpen(false);
|
||||
@@ -73,32 +98,56 @@ export function useSimpleCamera() {
|
||||
throw new Error('Erreur d\'accès à la caméra. Utilisez l\'option d\'importation de fichier comme alternative.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Media stream obtained successfully:', mediaStream.getVideoTracks().length, 'video tracks');
|
||||
setStream(mediaStream);
|
||||
|
||||
// Attendre que la modal soit rendue avant d'assigner le stream
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
if (videoRef.current && mediaStream && mediaStream.active) {
|
||||
const video = videoRef.current;
|
||||
console.log('Assigning stream to video element');
|
||||
console.log('Assigning stream to video element, tracks:', mediaStream.getVideoTracks().length);
|
||||
|
||||
video.srcObject = mediaStream;
|
||||
|
||||
// Forcer le play avec gestion d'erreur
|
||||
// Configuration vidéo pour production
|
||||
video.setAttribute('autoplay', 'true');
|
||||
video.setAttribute('playsinline', 'true');
|
||||
video.setAttribute('muted', 'true');
|
||||
|
||||
// Événements de diagnostic
|
||||
video.onloadedmetadata = () => {
|
||||
console.log('Video metadata loaded:', video.videoWidth, 'x', video.videoHeight);
|
||||
resolve(void 0);
|
||||
};
|
||||
|
||||
video.onerror = (e) => {
|
||||
console.error('Video element error:', e);
|
||||
resolve(void 0);
|
||||
};
|
||||
|
||||
// Forcer le play avec gestion d'erreur robuste
|
||||
video.play().then(() => {
|
||||
console.log('Video playing successfully');
|
||||
resolve(void 0);
|
||||
}).catch(playError => {
|
||||
console.error('Video play failed:', playError);
|
||||
// Réessayer après un délai
|
||||
setTimeout(() => {
|
||||
video.play().catch(e => console.error('Retry video play failed:', e));
|
||||
}, 200);
|
||||
video.play().catch(e => {
|
||||
console.error('Retry video play failed:', e);
|
||||
resolve(void 0);
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
} else {
|
||||
console.error('Video element not ready or stream inactive');
|
||||
resolve(void 0);
|
||||
}
|
||||
}, 200);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Camera start failed:', error);
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// Utilitaires de diagnostic caméra pour production
|
||||
export interface CameraCapabilities {
|
||||
hasMediaDevices: boolean;
|
||||
hasGetUserMedia: boolean;
|
||||
isHTTPS: boolean;
|
||||
userAgent: string;
|
||||
availableDevices: MediaDeviceInfo[];
|
||||
constraints: {
|
||||
video: boolean;
|
||||
audio: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export async function getCameraCapabilities(): Promise<CameraCapabilities> {
|
||||
const capabilities: CameraCapabilities = {
|
||||
hasMediaDevices: !!navigator.mediaDevices,
|
||||
hasGetUserMedia: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),
|
||||
isHTTPS: location.protocol === 'https:' || location.hostname === 'localhost',
|
||||
userAgent: navigator.userAgent,
|
||||
availableDevices: [],
|
||||
constraints: {
|
||||
video: false,
|
||||
audio: false
|
||||
}
|
||||
};
|
||||
|
||||
// Énumérer les appareils disponibles si possible
|
||||
if (capabilities.hasMediaDevices) {
|
||||
try {
|
||||
capabilities.availableDevices = await navigator.mediaDevices.enumerateDevices();
|
||||
} catch (error) {
|
||||
console.warn('Cannot enumerate devices:', error);
|
||||
}
|
||||
|
||||
// Tester les contraintes supportées
|
||||
if (capabilities.hasGetUserMedia) {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
capabilities.constraints.video = true;
|
||||
stream.getTracks().forEach(track => track.stop());
|
||||
} catch (error) {
|
||||
console.warn('Video not supported:', error);
|
||||
}
|
||||
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
capabilities.constraints.audio = true;
|
||||
stream.getTracks().forEach(track => track.stop());
|
||||
} catch (error) {
|
||||
console.warn('Audio not supported:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
export function logCameraCapabilities(capabilities: CameraCapabilities): void {
|
||||
console.group('🔍 Camera Capabilities Report');
|
||||
console.log('Media Devices API:', capabilities.hasMediaDevices ? '✅' : '❌');
|
||||
console.log('getUserMedia API:', capabilities.hasGetUserMedia ? '✅' : '❌');
|
||||
console.log('HTTPS Connection:', capabilities.isHTTPS ? '✅' : '⚠️');
|
||||
console.log('User Agent:', capabilities.userAgent);
|
||||
console.log('Video Support:', capabilities.constraints.video ? '✅' : '❌');
|
||||
console.log('Audio Support:', capabilities.constraints.audio ? '✅' : '❌');
|
||||
|
||||
if (capabilities.availableDevices.length > 0) {
|
||||
console.log('Available Devices:');
|
||||
capabilities.availableDevices.forEach((device, index) => {
|
||||
console.log(` ${index + 1}. ${device.kind}: ${device.label || 'Unknown'}`);
|
||||
});
|
||||
} else {
|
||||
console.log('Available Devices: None found or permission denied');
|
||||
}
|
||||
|
||||
console.groupEnd();
|
||||
}
|
||||
|
||||
export function generateCameraReport(capabilities: CameraCapabilities): string {
|
||||
const deviceCount = capabilities.availableDevices.filter(d => d.kind === 'videoinput').length;
|
||||
|
||||
let report = `=== Rapport Caméra Production ===\n`;
|
||||
report += `Navigateur: ${capabilities.userAgent.split(' ')[0]}\n`;
|
||||
report += `HTTPS: ${capabilities.isHTTPS ? 'Oui' : 'Non'}\n`;
|
||||
report += `API Média: ${capabilities.hasMediaDevices ? 'Disponible' : 'Indisponible'}\n`;
|
||||
report += `getUserMedia: ${capabilities.hasGetUserMedia ? 'Disponible' : 'Indisponible'}\n`;
|
||||
report += `Support Vidéo: ${capabilities.constraints.video ? 'Oui' : 'Non'}\n`;
|
||||
report += `Caméras détectées: ${deviceCount}\n`;
|
||||
|
||||
if (!capabilities.isHTTPS && location.hostname !== 'localhost') {
|
||||
report += `\n⚠️ ATTENTION: Connexion non sécurisée détectée.\n`;
|
||||
report += `La caméra peut ne pas fonctionner sans HTTPS.\n`;
|
||||
}
|
||||
|
||||
if (!capabilities.hasGetUserMedia) {
|
||||
report += `\n❌ ERREUR: API getUserMedia non disponible.\n`;
|
||||
report += `Utilisez un navigateur moderne (Chrome, Firefox, Safari).\n`;
|
||||
}
|
||||
|
||||
if (deviceCount === 0) {
|
||||
report += `\n⚠️ ATTENTION: Aucune caméra détectée.\n`;
|
||||
report += `Vérifiez les permissions ou connectez une caméra.\n`;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
Reference in new issue
Block a user