1
1
import { Controller } from '@hotwired/stimulus' ;
2
2
import { getComponent } from '@symfony/ux-live-component' ;
3
3
4
+ /**
5
+ * Heavily inspired by https://github.com/ngxson/smolvlm-realtime-webcam
6
+ */
4
7
export default class extends Controller {
5
8
async initialize ( ) {
6
9
this . component = await getComponent ( this . element ) ;
@@ -21,19 +24,40 @@ export default class extends Controller {
21
24
this . submitMessage ( ) ;
22
25
} ) ;
23
26
24
- this . video . srcObject = await navigator . mediaDevices . getUserMedia ( { video : true , audio : false } ) ;
27
+ await this . initCamera ( ) ;
25
28
} ;
26
29
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
+
27
41
submitMessage ( ) {
28
42
const input = document . getElementById ( 'chat-message' ) ;
29
43
const instruction = input . value ;
30
44
const image = this . captureImage ( ) ;
31
45
46
+ if ( null === image ) {
47
+ console . warn ( 'No image captured. Cannot submit message.' ) ;
48
+ return ;
49
+ }
50
+
32
51
this . component . action ( 'submit' , { instruction, image } ) ;
33
52
input . value = '' ;
34
53
}
35
54
36
55
captureImage ( ) {
56
+ if ( ! this . stream || ! this . video . videoWidth ) {
57
+ console . warn ( 'Video stream not ready for capture.' ) ;
58
+ return null ;
59
+ }
60
+
37
61
this . canvas . width = this . video . videoWidth ;
38
62
this . canvas . height = this . video . videoHeight ;
39
63
const context = this . canvas . getContext ( '2d' ) ;
0 commit comments