11import { Controller } from '@hotwired/stimulus' ;
22import { getComponent } from '@symfony/ux-live-component' ;
33
4+ /**
5+ * Heavily inspired by https://github.com/ngxson/smolvlm-realtime-webcam
6+ */
47export default class extends Controller {
58 async initialize ( ) {
69 this . component = await getComponent ( this . element ) ;
@@ -21,19 +24,40 @@ export default class extends Controller {
2124 this . submitMessage ( ) ;
2225 } ) ;
2326
24- this . video . srcObject = await navigator . mediaDevices . getUserMedia ( { video : true , audio : false } ) ;
27+ await this . initCamera ( ) ;
2528 } ;
2629
30+ async initCamera ( ) {
31+ try {
32+ this . stream = await navigator . mediaDevices . getUserMedia ( { video : true , audio : false } ) ;
33+ this . video . srcObject = this . stream ;
34+ console . log ( 'Camera access granted. Ready to start.' ) ;
35+ } catch ( err ) {
36+ console . error ( 'Error accessing camera:' , err ) ;
37+ alert ( `Error accessing camera: ${ err . name } . Make sure you've granted permission and are on HTTPS or localhost.` ) ;
38+ }
39+ }
40+
2741 submitMessage ( ) {
2842 const input = document . getElementById ( 'chat-message' ) ;
2943 const instruction = input . value ;
3044 const image = this . captureImage ( ) ;
3145
46+ if ( null === image ) {
47+ console . warn ( 'No image captured. Cannot submit message.' ) ;
48+ return ;
49+ }
50+
3251 this . component . action ( 'submit' , { instruction, image } ) ;
3352 input . value = '' ;
3453 }
3554
3655 captureImage ( ) {
56+ if ( ! this . stream || ! this . video . videoWidth ) {
57+ console . warn ( 'Video stream not ready for capture.' ) ;
58+ return null ;
59+ }
60+
3761 this . canvas . width = this . video . videoWidth ;
3862 this . canvas . height = this . video . videoHeight ;
3963 const context = this . canvas . getContext ( '2d' ) ;
0 commit comments