Harris
Harris
Explore posts from servers
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
already did! 😄
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
ty for the pointers
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
and it works great! no error 🙂
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
'use client';

import { create } from 'zustand';
import { setupAudio } from '@/lib/audio';
import { clearBufferedPlayerNodeBuffer } from '@/lib/audio/playback';
import { StarlightWebSocketRequestType, StopAudioRequest } from 'websocket/types';
import { useWebsocketStore } from '../websocket-store';
import { useTranscriptionStore } from './transcription-store';

type PlaybackStore = {
audioContext: AudioContext | null;
bufferedPlayerNode: AudioWorkletNode | null;
gainNode: GainNode | null;
socketState: string;
volume: number | null;
setVolume: (volume: number) => void;
clearAudio: () => void;
setup: () => void;
};

export const usePlaybackStore = create<PlaybackStore>((set, get) => {
return {
audioContext: null,
bufferedPlayerNode: null,
gainNode: null,
socketState: '',
volume: null,
setVolume: (desiredVolume: number) => {
const { gainNode } = get();
if (!gainNode) return;

const result = Math.max(0, Math.min(1, desiredVolume));
gainNode.gain.value = result;
set({ volume: result });

localStorage.setItem('volume', result.toString());
},
clearAudio: () => {
const sendToServer = useWebsocketStore.getState().sendToServer;
sendToServer({
type: StarlightWebSocketRequestType.stopAudio,
data: {},
} as StopAudioRequest);

const { bufferedPlayerNode } = get();
clearBufferedPlayerNodeBuffer(bufferedPlayerNode);
},
setup: async () => {
const { audioContext, bufferedPlayerNode, gainNode, volume } = await setupAudio();

set({ audioContext, bufferedPlayerNode, gainNode, volume });

useTranscriptionStore.getState().setupAudioRecorder();
},
};
});
'use client';

import { create } from 'zustand';
import { setupAudio } from '@/lib/audio';
import { clearBufferedPlayerNodeBuffer } from '@/lib/audio/playback';
import { StarlightWebSocketRequestType, StopAudioRequest } from 'websocket/types';
import { useWebsocketStore } from '../websocket-store';
import { useTranscriptionStore } from './transcription-store';

type PlaybackStore = {
audioContext: AudioContext | null;
bufferedPlayerNode: AudioWorkletNode | null;
gainNode: GainNode | null;
socketState: string;
volume: number | null;
setVolume: (volume: number) => void;
clearAudio: () => void;
setup: () => void;
};

export const usePlaybackStore = create<PlaybackStore>((set, get) => {
return {
audioContext: null,
bufferedPlayerNode: null,
gainNode: null,
socketState: '',
volume: null,
setVolume: (desiredVolume: number) => {
const { gainNode } = get();
if (!gainNode) return;

const result = Math.max(0, Math.min(1, desiredVolume));
gainNode.gain.value = result;
set({ volume: result });

localStorage.setItem('volume', result.toString());
},
clearAudio: () => {
const sendToServer = useWebsocketStore.getState().sendToServer;
sendToServer({
type: StarlightWebSocketRequestType.stopAudio,
data: {},
} as StopAudioRequest);

const { bufferedPlayerNode } = get();
clearBufferedPlayerNodeBuffer(bufferedPlayerNode);
},
setup: async () => {
const { audioContext, bufferedPlayerNode, gainNode, volume } = await setupAudio();

set({ audioContext, bufferedPlayerNode, gainNode, volume });

useTranscriptionStore.getState().setupAudioRecorder();
},
};
});
and then just set the zustand store volume based on what the client returns
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
import { setupBufferedPlayerProcessor } from './playback';

export async function setupAudio() {
const audioContext = new AudioContext({
sampleRate: 44100,
latencyHint: 'interactive',
});

// Setup AudioWorklet for buffered streaming playback
const blobURL = setupBufferedPlayerProcessor();
await audioContext.audioWorklet.addModule(blobURL);

const bufferedPlayerNode = new AudioWorkletNode(audioContext, 'buffered-player-processor');

// Gain node for volume control / mute
const gainNode = audioContext.createGain();

bufferedPlayerNode.connect(gainNode);
gainNode.connect(audioContext.destination);

// Retrieve browser volume from local storage
let volume = localStorage?.getItem('volume') ? parseFloat(localStorage.getItem('volume') as string) : 0.75;

gainNode.gain.value = volume;

return {
audioContext,
bufferedPlayerNode,
gainNode,
volume,
};
}
import { setupBufferedPlayerProcessor } from './playback';

export async function setupAudio() {
const audioContext = new AudioContext({
sampleRate: 44100,
latencyHint: 'interactive',
});

// Setup AudioWorklet for buffered streaming playback
const blobURL = setupBufferedPlayerProcessor();
await audioContext.audioWorklet.addModule(blobURL);

const bufferedPlayerNode = new AudioWorkletNode(audioContext, 'buffered-player-processor');

// Gain node for volume control / mute
const gainNode = audioContext.createGain();

bufferedPlayerNode.connect(gainNode);
gainNode.connect(audioContext.destination);

// Retrieve browser volume from local storage
let volume = localStorage?.getItem('volume') ? parseFloat(localStorage.getItem('volume') as string) : 0.75;

gainNode.gain.value = volume;

return {
audioContext,
bufferedPlayerNode,
gainNode,
volume,
};
}
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
I ended up moving it into my setupAudio function which only runs client side based on the store init effect
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
need to really deep dive the use client stuff more for a better understanding
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
beautiful, will try that out right now, ty
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
and into the store initalizer component that has my useEffect
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
i guess I move my localStorage code out of zustand
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
oh! wait
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
same with localstorage
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
that's true, but in this case I'm trying to handle a websocket & audiocontext which only really works client side I think? I don't think those can communicate nicely between boundary layers
28 replies
TTCTheo's Typesafe Cult
Created by Harris on 11/13/2023 in #questions
Zustand state being triggered server side even though I have "use client"?
i see, what would be the best approach in regards to wanting zustand to only want client side?
28 replies