Skip to content

Commit 15609b0

Browse files
authored
Merge pull request fac29b#62 from fac29b/front-camera
Front camera
2 parents a2915a0 + 7a2a945 commit 15609b0

7 files changed

Lines changed: 128 additions & 41 deletions

File tree

public/index.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,4 +663,13 @@ input:checked+.slider:before {
663663
width: 100%;
664664
max-width: 340px;
665665
}
666+
}
667+
668+
@keyframes fadeIn {
669+
from { opacity: 0; }
670+
to { opacity: 1; }
671+
}
672+
673+
.fade-in {
674+
animation: fadeIn 1s ease-in;
666675
}

public/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ <h1 class="picture-section-headline">You've got some ingredients but no idea wha
189189
<div class="video-btn-canvas">
190190
<video class="video"></video>
191191
<button class="take-picture">take a picture</button>
192+
<button id="switchCamera">Switch Camera</button>
192193
<canvas class="canvas"></canvas>
193194
<p class="chat-gpt-vision-text"></p>
194195
<button class="previous-page">previous page</button>

public/index.js

Lines changed: 111 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ import {
1212
stopAudio,
1313
createAudio,
1414
createUserRecipe,
15-
cacheData,
16-
CACHE_NAME_URL,
15+
cacheData,
16+
CACHE_NAME_URL,
1717
CACHE_NAME_AUDIO,
18-
emailObject,
1918
audioElement,
20-
2119
} from "./js_utilities/functions_and_variables.js";
2220

2321
import {
@@ -58,7 +56,9 @@ import {
5856
emailUserRecipeSection,
5957
} from "./js_utilities/query_selector.js";
6058

61-
59+
let currentCameraIndex = 0;
60+
const switchCameraButton = document.getElementById("switchCamera");
61+
let emailObject;
6262

6363
wantToTakeAPicture.addEventListener("click", () => {
6464
removeElements([pictureSectionHeadline, wantToTakeAPicture]);
@@ -141,7 +141,7 @@ sendToUserInbox.addEventListener("click", () => {
141141
});
142142

143143
sendToUserInboxBtn.addEventListener("click", () => {
144-
console.log(`userEmail ${userEmail.value}`);
144+
// console.log(`userEmail ${userEmail.value}`);
145145
console.log(emailObject);
146146
fetch(`/email?${createQuery(emailObject)}`)
147147
.then((response) => response.json())
@@ -165,32 +165,55 @@ recipeButtons.forEach((button) => {
165165
const userRecipe = createUserRecipe(button, dietaryRequirements, userText);
166166
console.log(userRecipe);
167167

168-
169-
170-
168+
const data = {};
171169

172170
const eventSource = new EventSource(`/stream?${createQuery(userRecipe)}`);
173171

174172
eventSource.onmessage = async function (event) {
175-
let data = JSON.parse(event.data);
176-
if (data.message) {
177-
if (data.message === "stop") {
173+
let eventData = JSON.parse(event.data);
174+
if (eventData.message) {
175+
if (eventData.message === "stop") {
178176
eventSource.close();
179177
return;
180178
}
181179
displayElements([gptResponseElement]);
182-
gptResponseElement.textContent += data.message;
180+
gptResponseElement.textContent += eventData.message;
183181
return;
184-
} else if (data.errorMessage === "invalid_api_key") {
182+
} else if (eventData.errorMessage === "invalid_api_key") {
185183
eventSource.close();
186-
console.log(data.errorMessage);
184+
console.log(eventData.errorMessage);
187185
displayElements([gptResponseElement, tryAgainBtn]);
188186
removeElements([loadingContainer]);
189187
gptResponseElement.innerHTML = defaultRecipe;
190188
return;
191189
}
192190

193-
if (data.audio) {
191+
if (eventData.audio) {
192+
data.audio = eventData.audio;
193+
}
194+
if (eventData.image) {
195+
data.image = eventData.image;
196+
}
197+
// console.log("cacheObject", data);
198+
console.log("data.audio", eventData.audio);
199+
console.log("data.image", eventData.image);
200+
201+
if (data.audio && data.image) {
202+
console.log(typeof data.image);
203+
removeElements([loadingContainer]);
204+
const imageUrl = data.image.data[0].url;
205+
console.log(`imageURL ${imageUrl}`);
206+
// await cacheData(imageUrl, CACHE_NAME_URL, "image");
207+
backgroundImg.src = imageUrl;
208+
backgroundImg.onload = () => {
209+
console.log("Image loaded successfully");
210+
211+
};
212+
backgroundImg.onerror = () => {
213+
console.error("Error loading image");
214+
};
215+
216+
///
194217
console.log(data.audio);
195218
const audio_data = createAudio(data.audio);
196219
console.log(`line 261: ${audio_data}`);
@@ -233,34 +256,85 @@ recipeButtons.forEach((button) => {
233256
});
234257
}
235258

236-
if (data.image) {
237-
console.log(typeof data.image);
238-
removeElements([loadingContainer]);
239-
const imageUrl = data.image.data[0].url;
240-
console.log(`imageURL ${imageUrl}`);
241-
await cacheData(imageUrl, CACHE_NAME_URL, "image");
242-
backgroundImg.src = imageUrl;
243-
backgroundImg.onload = () => {
244-
console.log("Image loaded successfully");
245-
};
246-
backgroundImg.onerror = () => {
247-
console.error("Error loading image");
248-
};
249-
}
259+
// if (data.image) {
260+
// console.log(typeof data.image);
261+
// removeElements([loadingContainer]);
262+
// const imageUrl = data.image.data[0].url;
263+
// console.log(`imageURL ${imageUrl}`);
264+
// // await cacheData(imageUrl, CACHE_NAME_URL, "image");
265+
// backgroundImg.src = imageUrl;
266+
// backgroundImg.onload = () => {
267+
// console.log("Image loaded successfully");
268+
// };
269+
// backgroundImg.onerror = () => {
270+
// console.error("Error loading image");
271+
// };
272+
// }
250273
};
251274
});
252275
});
253276

254277
// Picture section
255-
navigator.mediaDevices
256-
.getUserMedia(constraint)
257-
.then((stream) => {
278+
279+
async function getVideoDevices() {
280+
const devices = await navigator.mediaDevices.enumerateDevices();
281+
return devices.filter((device) => device.kind === "videoinput");
282+
}
283+
284+
async function startCamera(deviceId) {
285+
const constraints = {
286+
audio: false,
287+
video: {
288+
deviceId: deviceId ? { exact: deviceId } : undefined,
289+
width: { min: 1024, ideal: 1280, max: 1920 },
290+
height: { min: 576, ideal: 720, max: 1080 },
291+
},
292+
};
293+
294+
try {
295+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
258296
video.srcObject = stream;
259-
video.play();
260-
})
261-
.catch((error) => {
297+
await video.play();
298+
} catch (error) {
262299
console.error("Error accessing camera:", error);
263-
});
300+
}
301+
}
302+
303+
async function initializeCamera() {
304+
const videoDevices = await getVideoDevices();
305+
306+
if (videoDevices.length > 1) {
307+
switchCameraButton.style.display = "block";
308+
switchCameraButton.addEventListener("click", () => {
309+
currentCameraIndex = (currentCameraIndex + 1) % videoDevices.length;
310+
startCamera(videoDevices[currentCameraIndex].deviceId);
311+
});
312+
} else {
313+
switchCameraButton.style.display = "none";
314+
}
315+
316+
// Start with the rear camera if available
317+
const rearCameraDevice = videoDevices.find(
318+
(device) =>
319+
device.label.toLowerCase().includes("back") ||
320+
device.label.toLowerCase().includes("rear")
321+
);
322+
startCamera(
323+
rearCameraDevice ? rearCameraDevice.deviceId : videoDevices[0].deviceId
324+
);
325+
}
326+
327+
initializeCamera();
328+
329+
// navigator.mediaDevices
330+
// .getUserMedia(constraint)
331+
// .then((stream) => {
332+
// video.srcObject = stream;
333+
// video.play();
334+
// })
335+
// .catch((error) => {
336+
// console.error("Error accessing camera:", error);
337+
// });
264338

265339
function capturePhoto() {
266340
context.drawImage(video, 0, 0, 400, 100);

public/js_utilities/functions_and_variables.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
const CACHE_NAME_URL = "image-cache-v1";
44
const CACHE_NAME_AUDIO = "audio-cache-v2";
55
let audioElement = new Audio();
6-
let emailObject;
6+
77

88

99

@@ -162,4 +162,4 @@ function createAudio(data) {
162162

163163

164164

165-
export { defaultRecipe, CACHE_NAME_URL, audioElement, emailObject, CACHE_NAME_AUDIO, cacheData, createQuery, displayElements, displayElementsFlex, displayElementsGrid, removeElements, emptyTheElement, resetCheckedStateToFalse, playAudio, pauseAudio, stopAudio, createAudio, createUserRecipe }
165+
export { defaultRecipe, CACHE_NAME_URL, audioElement, CACHE_NAME_AUDIO, cacheData, createQuery, displayElements, displayElementsFlex, displayElementsGrid, removeElements, emptyTheElement, resetCheckedStateToFalse, playAudio, pauseAudio, stopAudio, createAudio, createUserRecipe }

public/js_utilities/query_selector.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ const constraint = {
4242
audio: false,
4343
video: {
4444
width: {min: 1024, ideal: 1280, max: 1920},
45-
height: {min: 576, ideal: 720, max: 1080}
45+
height: {min: 576, ideal: 720, max: 1080},
46+
facingMode: { ideal: 'environment' } // tells the browser to prefer the rear camera if available.
47+
48+
4649
}
4750
}
4851

public/url_folder.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
https://oaidalleapiprodscus.blob.core.windows.net/private/org-nYbqgo3O0LNnYYAoKAmApBfx/user-58Je7efi0iy880e2UYCdYpBm/img-QhUaTMW5KjXvVEFVqpbnc4WK.png?st=2024-07-30T12%3A45%3A56Z&se=2024-07-30T14%3A45%3A56Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-07-29T23%3A53%3A11Z&ske=2024-07-30T23%3A53%3A11Z&sks=b&skv=2023-11-03&sig=dk5PjiI69ok5GWveRY4lJjVFsgv1MhLFxe2OFGCWh5s%3D
1+
https://oaidalleapiprodscus.blob.core.windows.net/private/org-nYbqgo3O0LNnYYAoKAmApBfx/user-58Je7efi0iy880e2UYCdYpBm/img-fZ49pZbQpCxjm9FKRgrWUwV1.png?st=2024-08-01T13%3A04%3A59Z&se=2024-08-01T15%3A04%3A59Z&sp=r&sv=2023-11-03&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2024-07-31T23%3A34%3A47Z&ske=2024-08-01T23%3A34%3A47Z&sks=b&skv=2023-11-03&sig=jsB0y%2BY7/emg4Ic4UcC%2B3X%2BNip9uAN4c4p4cAx%2BGr%2B4%3D

speech.mp3

-130 KB
Binary file not shown.

0 commit comments

Comments
 (0)