@christianriedl/utils 1.0.104 → 1.0.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/iOpenAI.d.ts CHANGED
@@ -6,6 +6,6 @@ export interface ICompleteData {
6
6
  }
7
7
  export interface IOpenAIService extends ISpeechService {
8
8
  complete(prompt: string): Promise<ICompleteData>;
9
- completeImage(prompt: string, url: string): Promise<object>;
9
+ completeImage(prompt: string, url: string): Promise<ICompleteData>;
10
10
  completeJson(prompt: string, schema?: object): Promise<object>;
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/utils",
3
- "version": "1.0.104",
3
+ "version": "1.0.105",
4
4
  "description": "Interfaces, local storage, service worker, configuration, application state",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -2,11 +2,12 @@
2
2
  import { onMounted, onUnmounted, ref } from "vue";
3
3
  import { MediaDeviceKind, Resolution } from '@christianriedl/utils';
4
4
 
5
- const props = withDefaults(defineProps<{
6
- resolution?: Resolution; facingMode?: string; autoplay?: boolean, playsinline?: boolean, constraints?: object }>(),
7
- { resolution: { width: 1920, height: 1080}, facingMode: "environment", autoplay: true, playsinline: true });
5
+ const props = withDefaults(defineProps<{resolution: Resolution; facingMode?: string; autoplay?: boolean, playsinline?: boolean, constraints?: any}>(),
6
+ { facingMode: "environment", autoplay: true, playsinline: true });
8
7
  const emits = defineEmits(["loading", "started", "stopped", "paused", "resumed", "camera-change", "snapshot", "error" ]);
9
8
 
9
+ const resolution = props.resolution ? props.resolution : { width: 1920, height: 1080};
10
+
10
11
  onMounted(() => {
11
12
  if (!navigator.mediaDevices)
12
13
  throw new Error("Media devices not available");
@@ -28,8 +29,8 @@
28
29
 
29
30
  const constraints = props.constraints || {
30
31
  video: {
31
- width: props.resolution.width,
32
- height: props.resolution.height,
32
+ width: resolution.width,
33
+ height: resolution.height,
33
34
  facingMode: props.facingMode,
34
35
  deviceId: {},
35
36
  },
@@ -56,9 +57,7 @@
56
57
  emits("loading");
57
58
 
58
59
  try {
59
- stream.value = await navigator.mediaDevices.getUserMedia(
60
- constraints
61
- );
60
+ stream.value = await navigator.mediaDevices.getUserMedia(constraints);
62
61
 
63
62
  if (!video.value) throw new Error("Video ref is null");
64
63
 
@@ -70,11 +69,11 @@
70
69
  }
71
70
  };
72
71
 
73
- function snapshot (resolution: Resolution = props.resolution, type = "image/png", quality?: number): Promise<Blob | null> {
72
+ function snapshot (res: Resolution = resolution, type = "image/png", quality?: number): Promise<string | undefined> {
74
73
  if (!video.value) throw new Error("Video ref is null");
75
74
  if (!canvas.value) throw new Error("Canvas ref is null");
76
75
 
77
- const { width, height } = resolution;
76
+ const { width, height } = res;
78
77
 
79
78
  canvas.value.width = width;
80
79
  canvas.value.height = height;
@@ -82,14 +81,9 @@
82
81
  canvas.value.getContext("2d")?.drawImage(video.value, 0, 0, width, height);
83
82
 
84
83
  return new Promise((resolve) => {
85
- canvas.value?.toBlob(
86
- (blob: Blob | null) => {
87
- emits("snapshot", blob);
88
- resolve(blob);
89
- },
90
- type,
91
- quality
92
- );
84
+ const data = canvas.value?.toDataURL(type, quality);
85
+ emits("snapshot", data);
86
+ resolve(data);
93
87
  });
94
88
  };
95
89
 
@@ -114,6 +108,14 @@
114
108
  stream.value?.getTracks().forEach((track) => track.stop());
115
109
  emits("stopped");
116
110
  };
111
+ defineExpose({
112
+ start,
113
+ stop,
114
+ pause,
115
+ resume,
116
+ snapshot,
117
+ devices
118
+ })
117
119
  </script>
118
120
 
119
121
  <template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { inject, ref, toRef, computed, onUnmounted, InstanceType } from 'vue';
2
+ import { inject, ref, toRef, computed, onUnmounted } from 'vue';
3
3
  import { appStateSymbol, appConfigSymbol, getOpenAISymbol, IOpenAIService, ICompleteData, ESize } from '@christianriedl/utils';
4
4
  import Microphone from '@christianriedl/utils/src/components/Microphone.vue';
5
5
  import Camera from '@christianriedl/utils/src/components/Camera.vue';
@@ -22,8 +22,15 @@
22
22
  });
23
23
 
24
24
  async function onComplete() {
25
+ let answer: ICompleteData;
25
26
  replyLines.value = [ "WAITING ..." ];
26
- const answer = await openAI.complete(question.value);
27
+ if (isCamera.value && camera.value) {
28
+ const dataurl = await camera.value.snapshot();
29
+ answer = await openAI.completeImage(question.value, dataurl!);
30
+ }
31
+ else {
32
+ answer = await openAI.complete(question.value);
33
+ }
27
34
  if (answer && answer.choices && answer.choices.length > 0) {
28
35
  replyLines.value = answer.choices[0].split('\n');
29
36
  }
@@ -36,25 +43,14 @@
36
43
  }
37
44
  function onCamera() {
38
45
  isCamera.value = !isCamera.value;
46
+ if (isCamera.value && !question.value) {
47
+ question.value = "Was erkennst du auf dem Bild ?";
48
+ }
39
49
  if (!isCamera.value && camera.value) {
40
50
  camera.value.stop();
41
51
  camera.value = undefined;
42
52
  }
43
53
  }
44
- async function onSnapshot() {
45
- if (camera.value) {
46
- const blob = await camera.value?.snapshot();
47
- const url = URL.createObjectURL(blob);
48
- replyLines.value = [ "WAITING ..." ];
49
- const answer = await openAI.complete(question.value);
50
- if (answer && answer.choices && answer.choices.length > 0) {
51
- replyLines.value = answer.choices[0].split('\n');
52
- }
53
- else {
54
- replyLines.value = [ "NO CORRECT ANSWER" ];
55
- }
56
- }
57
- }
58
54
  </script>
59
55
 
60
56
  <template>
@@ -66,16 +62,22 @@
66
62
  <v-col :cols="12 - qcols">
67
63
  <v-btn @click="onComplete">AI</v-btn>
68
64
  <microphone lang="de" @result="onResult"></microphone>
69
- <v-btn :variant="tonal" :class="bg-office" @click="onCamera">
65
+ <v-btn variant="tonal" class="bg-office" @click="onCamera">
70
66
  <v-icon size="large" icon="$webcam" color="primary"></v-icon>
71
67
  </v-btn>
72
68
  </v-col>
73
69
  </v-row>
74
70
  <v-row v-if="isCamera" dense align="center">
75
- <camera :resolution="{ width: 375, height: 812 }" ref="camera" autoplay></camera>
76
- <v-btn @click="onSnapshot">Create snapshot</v-btn>
71
+ <v-col cols="6">
72
+ <camera :resolution="{ width: 640, height: 480 }" ref="camera" autoplay></camera>
73
+ </v-col>
74
+ <v-col cols="6">
75
+ <v-row v-for="(line, index) in replyLines" :key=index dense align="center">
76
+ <v-col cols="12">{{line}}</v-col>
77
+ </v-row>
78
+ </v-col>
77
79
  </v-row>
78
- <v-row v-for="(line, index) in replyLines" :key=index dense align="center">
80
+ <v-row v-else v-for="(line, index) in replyLines" :key=index dense align="center">
79
81
  <v-col cols="12">{{line}}</v-col>
80
82
  </v-row>
81
83
  </v-container>