Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit d7fa33f

Browse files
committed
feat: add demo of GPT vision capabilities based on video stream
1 parent bc225f4 commit d7fa33f

File tree

13 files changed

+469
-271
lines changed

13 files changed

+469
-271
lines changed

assets/app.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ import './styles/app.css';
44
import './styles/audio.css';
55
import './styles/blog.css';
66
import './styles/youtube.css';
7+
import './styles/video.css';
78
import './styles/wikipedia.css';
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {Controller} from '@hotwired/stimulus';
2+
import {getComponent} from '@symfony/ux-live-component';
3+
4+
export default class extends Controller {
5+
async initialize() {
6+
this.component = await getComponent(this.element);
7+
8+
this.video = document.getElementById('videoFeed');
9+
this.canvas = document.getElementById('canvas');
10+
11+
const input = document.getElementById('chat-message');
12+
input.addEventListener('keypress', (event) => {
13+
if (event.key === 'Enter') {
14+
this.submitMessage();
15+
}
16+
});
17+
input.focus();
18+
19+
const submitButton = document.getElementById('chat-submit');
20+
submitButton.addEventListener('click', (event) => {
21+
this.submitMessage();
22+
});
23+
24+
this.video.srcObject = await navigator.mediaDevices.getUserMedia({video: true, audio: false});
25+
};
26+
27+
submitMessage() {
28+
const input = document.getElementById('chat-message');
29+
const instruction = input.value;
30+
const image = this.captureImage();
31+
32+
this.component.action('submit', { instruction, image });
33+
input.value = '';
34+
}
35+
36+
captureImage() {
37+
this.canvas.width = this.video.videoWidth;
38+
this.canvas.height = this.video.videoHeight;
39+
const context = this.canvas.getContext('2d');
40+
context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
41+
return this.canvas.toDataURL('image/jpeg', 0.8);
42+
}
43+
}

assets/icons/tabler/video-filled.svg

Lines changed: 1 addition & 0 deletions
Loading

assets/styles/video.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.video {
2+
body&, .card-img-top {
3+
background: #26931e;
4+
background: linear-gradient(0deg, #186361 0%, #26931e 100%);
5+
}
6+
7+
.card-img-top {
8+
color: #ffffff;
9+
}
10+
11+
&.chat {
12+
#chat-submit {
13+
&:hover {
14+
background: #186361;
15+
border-color: #186361;
16+
}
17+
}
18+
}
19+
20+
footer {
21+
color: #ffffff;
22+
23+
a {
24+
color: #ffffff;
25+
}
26+
}
27+
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"ext-iconv": "*",
1010
"codewithkyrian/chromadb-php": "^0.3.0",
1111
"league/commonmark": "^2.6",
12-
"php-llm/llm-chain-bundle": "^0.19",
12+
"php-llm/llm-chain-bundle": "^0.20",
1313
"runtime/frankenphp-symfony": "^0.2.0",
1414
"symfony/asset": "7.2.*",
1515
"symfony/asset-mapper": "7.2.*",

0 commit comments

Comments
 (0)