Skip to content

Commit 8b21c8c

Browse files
authored
Gemini integration (#218)
## Description Adds the Gemini integration. It's available to import from the `@fishjam-cloud/js-server-sdk/gemini` path. Transcription example has been adjusted as well. ## Documentation impact - [ ] Documentation update required - [ ] Documentation updated [in another PR](_) - [x] No documentation update required ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
1 parent 5937dda commit 8b21c8c

6 files changed

Lines changed: 84 additions & 8 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const TRANSCRIPTION_MODEL = 'gemini-live-2.5-flash-preview';
1+
export const TRANSCRIPTION_MODEL = 'gemini-2.5-flash-native-audio-preview-09-2025';

examples/transcription/src/service/transcription.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
FishjamConfig,
3-
FishjamAgent,
43
FishjamWSNotifier,
54
PeerConnected,
65
PeerDisconnected,
@@ -9,6 +8,7 @@ import {
98
FishjamClient,
109
RoomId,
1110
} from '@fishjam-cloud/js-server-sdk';
11+
import GeminiIntegration from '@fishjam-cloud/js-server-sdk/gemini';
1212
import { GoogleGenAI, LiveServerMessage, Modality, Session } from '@google/genai';
1313
import { TRANSCRIPTION_MODEL } from '../const';
1414

@@ -20,7 +20,7 @@ export class TranscriptionService {
2020
fishjamClient: FishjamClient;
2121

2222
constructor(fishjamConfig: FishjamConfig, geminiKey: string) {
23-
this.ai = new GoogleGenAI({ apiKey: geminiKey });
23+
this.ai = GeminiIntegration.createClient({ apiKey: geminiKey });
2424
this.fishjamConfig = fishjamConfig;
2525
this.fishjamClient = new FishjamClient(fishjamConfig);
2626
this.initFishjam();
@@ -51,7 +51,7 @@ export class TranscriptionService {
5151
agent: agent,
5252
} = await this.fishjamClient.createAgent(
5353
message.roomId,
54-
{},
54+
{ output: GeminiIntegration.geminiInputAudioSettings },
5555
{
5656
onClose: (code, reason) => console.log(`Fishjam agent websocket closed. code: ${code}, reason: ${reason}`),
5757
onError: (error) => console.error('Fishjam agent websocket error: %O', error),
@@ -67,7 +67,7 @@ export class TranscriptionService {
6767
const session = await this.ai.live.connect({
6868
model: TRANSCRIPTION_MODEL,
6969
config: {
70-
responseModalities: [Modality.TEXT],
70+
responseModalities: [Modality.AUDIO],
7171
inputAudioTranscription: {},
7272
},
7373
callbacks: {
@@ -115,10 +115,11 @@ export class TranscriptionService {
115115
const { data, peerId } = message;
116116

117117
const session = this.peerSessions.get(peerId);
118+
118119
session?.sendRealtimeInput({
119120
audio: {
120121
data: data.toBase64(),
121-
mimeType: 'audio/pcm;rate=16000',
122+
mimeType: GeminiIntegration.inputMimeType,
122123
},
123124
});
124125
}

packages/js-server-sdk/package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"dist"
2525
],
2626
"exports": {
27-
".": "./dist/index.js"
27+
".": "./dist/index.js",
28+
"./gemini": "./dist/integrations/gemini.js"
2829
},
2930
"scripts": {
3031
"build": "tsup --dts-resolve",
@@ -37,6 +38,7 @@
3738
"tsup": {
3839
"entry": [
3940
"src/index.ts",
41+
"src/integrations/gemini.ts",
4042
"src/proto.ts"
4143
],
4244
"noExternal": [
@@ -54,6 +56,14 @@
5456
"axios": "^1.7.9",
5557
"uuid": "^11.1.0"
5658
},
59+
"peerDependencies": {
60+
"@google/genai": "^1.0.0"
61+
},
62+
"peerDependenciesMeta": {
63+
"@google/genai": {
64+
"optional": true
65+
}
66+
},
5767
"devDependencies": {
5868
"@fishjam-cloud/fishjam-openapi": "workspace:*",
5969
"@fishjam-cloud/fishjam-proto": "workspace:*",
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { GoogleGenAI, GoogleGenAIOptions } from '@google/genai' with { 'resolution-mode': 'import' };
2+
import fishjamSDK from '../../package.json';
3+
import type { PeerOptionsAgentOutput } from '@fishjam-cloud/fishjam-openapi';
4+
import type { AudioCodecParameters } from '../agent';
5+
6+
const SDK_NAME = 'fishjam-js-server-sdk';
7+
8+
/**
9+
* A collection of settings for Google Gemini integration.
10+
*/
11+
export default {
12+
/**
13+
* Creates a GoogleGenAI client.
14+
* This function dynamically imports the "@google/genai" module,
15+
* so it will only be loaded when this function is called.
16+
*
17+
* @param options Configuration for the GoogleGenAI client.
18+
* @returns A GoogleGenAI instance.
19+
*/
20+
createClient: (options: GoogleGenAIOptions): GoogleGenAI => {
21+
// eslint-disable-next-line @typescript-eslint/no-require-imports
22+
const { GoogleGenAI } = require('@google/genai');
23+
const trackingHeader = { 'X-Goog-Api-Client': `${SDK_NAME}/${fishjamSDK.version}` };
24+
const finalOptions = {
25+
...options,
26+
httpOptions: {
27+
...options.httpOptions,
28+
headers: {
29+
...options.httpOptions?.headers,
30+
...trackingHeader,
31+
},
32+
},
33+
};
34+
return new GoogleGenAI(finalOptions);
35+
},
36+
37+
/**
38+
* Predefined audio settings for the agent's output track,
39+
* configured for Gemini's 24kHz audio output.
40+
*/
41+
geminiOutputAudioSettings: {
42+
encoding: 'pcm16',
43+
channels: 1,
44+
sampleRate: 24000,
45+
} as const satisfies AudioCodecParameters,
46+
47+
/**
48+
* Predefined audio settings for subscribing to room audio,
49+
* configured for Gemini's 16kHz audio input.
50+
*/
51+
geminiInputAudioSettings: {
52+
audioFormat: 'pcm16',
53+
audioSampleRate: 16000,
54+
} as const satisfies PeerOptionsAgentOutput,
55+
56+
/**
57+
* The MIME type for the audio data sent to Gemini.
58+
*/
59+
inputMimeType: 'audio/pcm;rate=16000' as const,
60+
};

packages/js-server-sdk/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
"lib": ["es2023"],
77
"module": "node16",
88
"target": "es2022",
9-
109
"strict": true,
1110
"esModuleInterop": true,
11+
"resolveJsonModule": true,
1212
"skipLibCheck": true,
1313
"declaration": true,
1414
"moduleResolution": "node16",

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,11 @@ __metadata:
858858
tsup: "npm:^8.4.0"
859859
typed-emitter: "npm:^2.1.0"
860860
uuid: "npm:^11.1.0"
861+
peerDependencies:
862+
"@google/genai": ^1.0.0
863+
peerDependenciesMeta:
864+
"@google/genai":
865+
optional: true
861866
languageName: unknown
862867
linkType: soft
863868

0 commit comments

Comments
 (0)