Skip to content

Feat/long file playback#993

Draft
mdydek wants to merge 8 commits intomainfrom
feat/long-file-playback
Draft

Feat/long file playback#993
mdydek wants to merge 8 commits intomainfrom
feat/long-file-playback

Conversation

@mdydek
Copy link
Contributor

@mdydek mdydek commented Mar 20, 2026

Closes #735

⚠️ Breaking changes ⚠️

Introduced changes

Checklist

  • Linked relevant issue
  • Updated relevant documentation
  • Added/Conducted relevant tests
  • Performed self-review of the code
  • Updated Web Audio API coverage
  • Added support for web
  • Updated old arch android spec file

@mdydek mdydek added the feature New feature label Mar 20, 2026
private:
std::shared_ptr<AudioFileDecoderState> decoderState_;
std::atomic<float> volume_;
bool FFmpegNeeded_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
bool FFmpegNeeded_;
bool requiresFFmpeg_;

Comment on lines +29 to +38
export const AudioComponentContext = createContext<AudioComponentContextType>({
play: () => {},
pause: () => {},
volume: 1,
setVolume: () => {},
muted: false,
setMuted: () => {},
isReady: false,
playbackState: 'idle',
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be great to extract it to separate file ie. audioTagContex.ts

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and on second though we could go with

createContext<AudioComponentContextType | null>(null);

plus a helper hook

function useAudioTagContext() {
  const context = useContext(AudioComponentContext);

  if (!context) {
    throw new Error("useAudioTagContext used within a provider tag!");
  }

  return context; // always returns AudioComponentContextType
}

useState<AudioTagPlaybackState>('idle');

const volumeStateRef = useRef(volumeState);
volumeStateRef.current = volumeState;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be an useEffect

volumeStateRef.current = volumeState;

const mutedStateRef = useRef(mutedState);
mutedStateRef.current = mutedState;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be an useEffect

mutedStateRef.current = mutedState;

const contextRef = useRef(context);
contextRef.current = context;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Comment on lines +120 to +149
useEffect(() => {
if (!context || !path) {
return;
}

const run = async () => {
if (path.startsWith('http')) {
const response = await fetch(path);
const arrayBuffer = await response.arrayBuffer();
attachNode(context.context.createFileSource(arrayBuffer));
} else {
attachNode(context.context.createFileSource(path));
}
};

setIsReady(false);
setPlaybackState('idle');
run();

return () => {
const prev = nodeRef.current;
if (prev) {
prev.onEnded = '0';
}
prev?.disconnect(undefined);
nodeRef.current = null;
setIsReady(false);
setPlaybackState('idle');
};
}, [path, context, attachNode]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means that each time we toggle play state whe fetch and load the file again

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can try using the vercels react best practices to cleanup a bit the component code :)

preservesPitch: boolean;
volume: number;
children?: ReactNode;
context: BaseAudioContext | null; // null on web, since web do not use AudioContext for audio tag
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
context: BaseAudioContext | null; // null on web, since web do not use AudioContext for audio tag
context?: BaseAudioContext; // optional on web, since web do not use AudioContext for audio tag

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Buffering Audio from files

3 participants