changes: Fix iphone rear camera showing
This commit is contained in:
147
app/page.tsx
147
app/page.tsx
@@ -54,7 +54,7 @@ function HomePageContent() {
|
||||
console.log('starting stream....')
|
||||
try {
|
||||
const newStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { deviceId: { exact: deviceId } },
|
||||
video: { deviceId: deviceId ? { ideal: deviceId } : true },
|
||||
});
|
||||
|
||||
console.log(newStream)
|
||||
@@ -80,73 +80,130 @@ function HomePageContent() {
|
||||
useEffect(() => {
|
||||
const initializeCamera = async () => {
|
||||
try {
|
||||
// Check if there's a stored preference first
|
||||
// Load history first
|
||||
setHistory(getHistory());
|
||||
|
||||
// Check if there's a stored preference
|
||||
const storedDeviceId = localStorage.getItem('selectedCameraDeviceId');
|
||||
|
||||
let targetStream: MediaStream;
|
||||
|
||||
if (storedDeviceId) {
|
||||
// User has a saved preference, use it
|
||||
console.log('Using stored camera preference:', storedDeviceId);
|
||||
targetStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { deviceId: { exact: storedDeviceId } }
|
||||
});
|
||||
} else {
|
||||
// No preference - try to use back/environment camera
|
||||
console.log('No stored preference - requesting back camera (facingMode: environment)');
|
||||
try {
|
||||
targetStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: 'environment' }
|
||||
});
|
||||
} catch (err) {
|
||||
// Fallback: facingMode might not be supported, use default
|
||||
console.log('facingMode not supported, using default camera');
|
||||
targetStream = await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
console.log('✅ Found stored camera preference, attempting to use it...');
|
||||
// Step 1: Request permission with stored device
|
||||
const permissionStream = await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
permissionStream.getTracks().forEach(track => track.stop());
|
||||
|
||||
// Step 2: Enumerate devices
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const videoInputs = devices.filter(d => d.kind === 'videoinput');
|
||||
console.log('📹 Available cameras:', videoInputs.map(d => ({ label: d.label, id: d.deviceId })));
|
||||
setVideoDevices(videoInputs);
|
||||
|
||||
if (videoInputs.length === 0) {
|
||||
setCameraStatus('no_devices');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if stored device still exists
|
||||
const storedDevice = videoInputs.find(d => d.deviceId === storedDeviceId);
|
||||
if (storedDevice) {
|
||||
console.log('✅ Using stored camera:', storedDevice.label);
|
||||
setSelectedDeviceId(storedDevice.deviceId);
|
||||
await startStream(storedDevice.deviceId);
|
||||
return;
|
||||
} else {
|
||||
console.log('⚠️ Stored camera not found, will search for back camera');
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the stream temporarily to enumerate devices
|
||||
targetStream.getTracks().forEach(track => track.stop());
|
||||
// No stored preference or stored device not found - find back camera
|
||||
console.log('🔍 Attempting to open back camera using facingMode: environment');
|
||||
|
||||
// Now enumerate devices - deviceIds will be stable after permission granted
|
||||
// Step 1: Try to open back camera directly with facingMode
|
||||
let backCameraStream: MediaStream;
|
||||
try {
|
||||
backCameraStream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: 'environment' }
|
||||
});
|
||||
console.log('✅ Got stream with facingMode: environment');
|
||||
} catch (err) {
|
||||
console.log('⚠️ facingMode: environment failed, trying default camera');
|
||||
backCameraStream = await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
}
|
||||
|
||||
// Step 2: Get the actual device that was used
|
||||
const track = backCameraStream.getVideoTracks()[0];
|
||||
const settings = track.getSettings();
|
||||
console.log('📸 Camera settings:', {
|
||||
deviceId: settings.deviceId,
|
||||
facingMode: settings.facingMode,
|
||||
label: track.label
|
||||
});
|
||||
|
||||
// Step 3: Enumerate all devices
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
const videoInputs = devices.filter(d => d.kind === 'videoinput');
|
||||
console.log('📹 All cameras:', videoInputs.map(d => ({ label: d.label, id: d.deviceId })));
|
||||
setVideoDevices(videoInputs);
|
||||
|
||||
if (videoInputs.length === 0) {
|
||||
backCameraStream.getTracks().forEach(track => track.stop());
|
||||
setCameraStatus('no_devices');
|
||||
return;
|
||||
}
|
||||
|
||||
// Load history
|
||||
setHistory(getHistory());
|
||||
// Step 4: Verify if we got the back camera
|
||||
let selectedDevice: MediaDeviceInfo | undefined;
|
||||
|
||||
// Find which camera was actually used
|
||||
const activeTrack = targetStream.getVideoTracks()[0];
|
||||
const activeDeviceId = activeTrack?.getSettings().deviceId;
|
||||
|
||||
let finalDevice: MediaDeviceInfo;
|
||||
|
||||
if (activeDeviceId && videoInputs.find(d => d.deviceId === activeDeviceId)) {
|
||||
// Found the device that was actually used
|
||||
finalDevice = videoInputs.find(d => d.deviceId === activeDeviceId)!;
|
||||
console.log('Using camera:', finalDevice.label || 'Unknown');
|
||||
if (settings.facingMode === 'environment') {
|
||||
// Perfect! We got the environment camera
|
||||
console.log('✅ Confirmed back camera by facingMode');
|
||||
selectedDevice = videoInputs.find(d => d.deviceId === settings.deviceId);
|
||||
} else {
|
||||
// Fallback: try to find back camera by label
|
||||
const backCameraKeywords = ['back', 'rear', 'trasera', 'environment', 'facing back'];
|
||||
finalDevice = videoInputs.find(d =>
|
||||
// We might have gotten the front camera, let's search manually
|
||||
console.log('⚠️ facingMode is not "environment", searching manually...');
|
||||
|
||||
// Stop the current stream
|
||||
backCameraStream.getTracks().forEach(track => track.stop());
|
||||
|
||||
// Search by label keywords
|
||||
const backCameraKeywords = ['back', 'rear', 'trasera', 'environment', 'posterior'];
|
||||
selectedDevice = videoInputs.find(d =>
|
||||
backCameraKeywords.some(keyword => d.label.toLowerCase().includes(keyword))
|
||||
) || videoInputs[0];
|
||||
console.log('Fallback to camera:', finalDevice.label || 'Unknown');
|
||||
);
|
||||
|
||||
if (!selectedDevice && videoInputs.length > 1) {
|
||||
// iOS fallback: try index 1 (usually back camera)
|
||||
console.log('📱 Trying camera at index 1 for iOS');
|
||||
selectedDevice = videoInputs[1];
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedDeviceId(finalDevice.deviceId);
|
||||
localStorage.setItem('selectedCameraDeviceId', finalDevice.deviceId);
|
||||
await startStream(finalDevice.deviceId);
|
||||
// Fallback to first camera
|
||||
if (!selectedDevice) {
|
||||
selectedDevice = videoInputs[0];
|
||||
console.log('⚠️ Using first camera as fallback');
|
||||
}
|
||||
|
||||
console.log('🎯 Selected camera:', selectedDevice.label, selectedDevice.deviceId);
|
||||
setSelectedDeviceId(selectedDevice.deviceId);
|
||||
localStorage.setItem('selectedCameraDeviceId', selectedDevice.deviceId);
|
||||
|
||||
// If we still have the stream from facingMode and it matches, use it
|
||||
if (settings.facingMode === 'environment' && settings.deviceId === selectedDevice.deviceId) {
|
||||
console.log('♻️ Reusing existing stream');
|
||||
setStream(backCameraStream);
|
||||
setCameraStatus('active');
|
||||
if (videoRef.current) {
|
||||
videoRef.current.srcObject = backCameraStream;
|
||||
}
|
||||
} else {
|
||||
// Start fresh stream with selected device
|
||||
backCameraStream.getTracks().forEach(track => track.stop());
|
||||
await startStream(selectedDevice.deviceId);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
// Permission denied or no camera
|
||||
console.error('Error accessing camera or enumerating devices:', err);
|
||||
console.error('❌ Error accessing camera:', err);
|
||||
setCameraStatus('denied');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user