feat(core): support splitting audio blobs before submitting to backend (#11572)

fix AF-2484
This commit is contained in:
pengx17
2025-04-09 12:44:37 +00:00
parent ba875a120f
commit 34b6e7ef88
6 changed files with 226 additions and 51 deletions

View File

@@ -1,4 +1,4 @@
import { encodeAudioBlobToOpus } from '@affine/core/utils/webm-encoding';
import { encodeAudioBlobToOpusSlices } from '@affine/core/utils/webm-encoding';
import { DebugLogger } from '@affine/debug';
import { AiJobStatus } from '@affine/graphql';
import track from '@affine/track';
@@ -115,17 +115,19 @@ export class AudioAttachmentBlock extends Entity<AttachmentBlockModel> {
const job = this.framework.createEntity(AudioTranscriptionJob, {
blobId: this.props.props.sourceId,
blockProps: transcriptionBlockProps,
getAudioFile: async () => {
getAudioFiles: async () => {
const buffer = await this.audioMedia.getBuffer();
if (!buffer) {
throw new Error('No audio buffer available');
}
const encodedBuffer = await encodeAudioBlobToOpus(buffer, 64000);
const blob = new Blob([encodedBuffer], { type: this.props.props.type });
const file = new File([blob], this.props.props.name, {
type: this.props.props.type,
const slices = await encodeAudioBlobToOpusSlices(buffer, 64000);
const files = slices.map((slice, index) => {
const blob = new Blob([slice], { type: 'audio/opus' });
return new File([blob], this.props.props.name + `-${index}.opus`, {
type: 'audio/opus',
});
});
return file;
return files;
},
});

View File

@@ -12,7 +12,7 @@ import type { WorkspaceService } from '../../workspace';
export class AudioTranscriptionJobStore extends Entity<{
readonly blobId: string;
readonly getAudioFile: () => Promise<File>;
readonly getAudioFiles: () => Promise<File[]>;
}> {
constructor(
private readonly workspaceService: WorkspaceService,
@@ -41,13 +41,13 @@ export class AudioTranscriptionJobStore extends Entity<{
if (!graphqlService) {
throw new Error('No graphql service available');
}
const file = await this.props.getAudioFile();
const files = await this.props.getAudioFiles();
const response = await graphqlService.gql({
query: submitAudioTranscriptionMutation,
variables: {
workspaceId: this.currentWorkspaceId,
blobId: this.props.blobId,
blob: file,
blobs: files,
},
});
if (!response.submitAudioTranscription?.id) {

View File

@@ -46,7 +46,7 @@ const logger = new DebugLogger('audio-transcription-job');
export class AudioTranscriptionJob extends Entity<{
readonly blockProps: TranscriptionBlockProps;
readonly blobId: string;
readonly getAudioFile: () => Promise<File>;
readonly getAudioFiles: () => Promise<File[]>;
}> {
constructor(
private readonly workspaceServerService: WorkspaceServerService,
@@ -68,7 +68,7 @@ export class AudioTranscriptionJob extends Entity<{
AudioTranscriptionJobStore,
{
blobId: this.props.blobId,
getAudioFile: this.props.getAudioFile,
getAudioFiles: this.props.getAudioFiles,
}
);