mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Wire all up to BlobUtils
This commit is contained in:
@@ -314,7 +314,7 @@ export function LLMAttachmentMenu(props: {
|
||||
<Link onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
showImageDataURLInNewTab(draftInput?.urlImage?.imgDataUrl || '');
|
||||
void showImageDataURLInNewTab(draftInput?.urlImage?.imgDataUrl || '');
|
||||
}}>
|
||||
open <LaunchIcon sx={{ mx: 0.5, fontSize: 16 }} />
|
||||
</Link>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { youTubeGetVideoData } from '~/modules/youtube/useYouTubeTranscript';
|
||||
|
||||
import { Is } from '~/common/util/pwaUtils';
|
||||
import { agiCustomId, agiUuid } from '~/common/util/idUtils';
|
||||
import { base64ToArrayBuffer } from '~/common/util/urlUtils';
|
||||
import { convert_Base64_To_UInt8Array } from '~/common/util/blobUtils';
|
||||
import { htmlTableToMarkdown } from '~/common/util/htmlTableToMarkdown';
|
||||
import { humanReadableHyphenated } from '~/common/util/textUtils';
|
||||
import { pdfToImageDataURLs, pdfToText } from '~/common/util/pdfUtils';
|
||||
@@ -125,16 +125,20 @@ export async function attachmentLoadInputAsync(source: Readonly<AttachmentDraftS
|
||||
else
|
||||
edit({ inputError: 'No content found at this link' });
|
||||
} else if (file) {
|
||||
const data = base64ToArrayBuffer(file.data);
|
||||
edit({
|
||||
label: file.fileName || source.refUrl,
|
||||
// ref: source.refUrl,
|
||||
input: {
|
||||
mimeType: file.mimeType,
|
||||
data: data,
|
||||
dataSize: data.byteLength,
|
||||
},
|
||||
});
|
||||
try {
|
||||
const dataArray = convert_Base64_To_UInt8Array(file.data, 'attachment-draft-load-input')
|
||||
edit({
|
||||
label: file.fileName || source.refUrl,
|
||||
// ref: source.refUrl,
|
||||
input: {
|
||||
mimeType: file.mimeType,
|
||||
data: dataArray.buffer,
|
||||
dataSize: dataArray.byteLength,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
edit({ inputError: `Issue downloading web file: ${error?.message || (typeof error === 'string' ? error : JSON.stringify(error))}` });
|
||||
}
|
||||
} else
|
||||
edit({ inputError: 'No content or file found at this link' });
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -6,15 +6,22 @@
|
||||
*/
|
||||
|
||||
import { canvasToDataURLAndMimeType } from './canvasUtils';
|
||||
import { createBlobURLFromDataURL } from './urlUtils';
|
||||
import { convert_Base64DataURL_To_Base64WithMimeType, convert_Base64WithMimeType_To_Blob, } from '~/common/util/blobUtils';
|
||||
|
||||
|
||||
/**
|
||||
* Opens an image Data URL in a new tab
|
||||
*/
|
||||
export function showImageDataURLInNewTab(imageDataURL: string) {
|
||||
const blobURL = createBlobURLFromDataURL(imageDataURL);
|
||||
return blobURL ? showBlobURLInNewTab(blobURL) : false;
|
||||
export async function showImageDataURLInNewTab(imageDataURL: string) {
|
||||
try {
|
||||
const { base64Data, mimeType } = convert_Base64DataURL_To_Base64WithMimeType(imageDataURL, 'showImageDataURLInNewTab');
|
||||
const imageBlob = await convert_Base64WithMimeType_To_Blob(base64Data, mimeType, 'showImageDataURLInNewTab')
|
||||
// NOTE: we don't really know when to release this, as the user may still be viewing the image in the new tab
|
||||
return URL.createObjectURL(imageBlob);
|
||||
} catch (error) {
|
||||
console.warn('showImageDataURLInNewTab: Failed to convert image Data URL to Blob URL.', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function showBlobURLInNewTab(blobURL: string) {
|
||||
|
||||
@@ -161,40 +161,3 @@ export function extractUrlsFromText(text: string): string[] {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Blob Object URL (that can be opened in a new tab with window.open, for instance)
|
||||
*/
|
||||
export function createBlobURLFromData(base64Data: string, mimeType: string) {
|
||||
const byteArray = base64ToUint8Array(base64Data);
|
||||
const blob = new Blob([byteArray], { type: mimeType });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
export function base64ToUint8Array(base64Data: string) {
|
||||
const binaryString = atob(base64Data);
|
||||
return Uint8Array.from(binaryString, char => char.charCodeAt(0));
|
||||
}
|
||||
|
||||
export function base64ToArrayBuffer(base64Data: string) {
|
||||
return base64ToUint8Array(base64Data).buffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Blob Object URL (that can be opened in a new tab with window.open, for instance) from a Data URL
|
||||
*/
|
||||
export function createBlobURLFromDataURL(dataURL: string) {
|
||||
if (!dataURL.startsWith('data:')) {
|
||||
console.error('createBlobURLFromDataURL: Invalid data URL', dataURL);
|
||||
return null;
|
||||
}
|
||||
const mimeType = dataURL.slice(5, dataURL.indexOf(';'));
|
||||
const base64Data = dataURL.slice(dataURL.indexOf(',') + 1);
|
||||
if (!mimeType || !base64Data) {
|
||||
console.error('createBlobURLFromDataURL: Invalid data URL', dataURL);
|
||||
return null;
|
||||
}
|
||||
return createBlobURLFromData(base64Data, mimeType);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { addDBImageAsset } from '~/modules/dblobs/dblobs.images';
|
||||
import type { MaybePromise } from '~/common/types/useful.types';
|
||||
import { DEFAULT_ADRAFT_IMAGE_MIMETYPE } from '~/common/attachment-drafts/attachment.pipeline';
|
||||
import { convertBase64Image, getImageDimensions } from '~/common/util/imageUtils';
|
||||
import { convert_Base64_To_UInt8Array } from '~/common/util/blobUtils';
|
||||
import { create_CodeExecutionInvocation_ContentFragment, create_CodeExecutionResponse_ContentFragment, create_FunctionCallInvocation_ContentFragment, createAnnotationsVoidFragment, createDMessageDataRefDBlob, createDVoidWebCitation, createErrorContentFragment, createImageContentFragment, createModelAuxVoidFragment, createTextContentFragment, DVoidModelAuxPart, isContentFragment, isModelAuxPart, isTextContentFragment, isVoidAnnotationsFragment, isVoidFragment } from '~/common/stores/chat/chat.fragments';
|
||||
import { ellipsizeMiddle } from '~/common/util/textUtils';
|
||||
import { metricsFinishChatGenerateLg, metricsPendChatGenerateLg } from '~/common/stores/metrics/metrics.chatgenerate';
|
||||
@@ -14,7 +15,6 @@ import type { AixClientDebugger, AixFrameId } from './debugger/memstore-aix-clie
|
||||
import { aixClientDebugger_completeFrame, aixClientDebugger_init, aixClientDebugger_recordParticleReceived, aixClientDebugger_setProfilerMeasurements, aixClientDebugger_setRequest } from './debugger/reassembler-debug';
|
||||
|
||||
import { AixChatGenerateContent_LL, DEBUG_PARTICLES } from './aix.client';
|
||||
import { base64ToUint8Array } from '~/common/util/urlUtils';
|
||||
|
||||
|
||||
// configuration
|
||||
@@ -400,8 +400,8 @@ export class ContentReassembler {
|
||||
|
||||
try {
|
||||
|
||||
// create blob and play audio
|
||||
const bytes = base64ToUint8Array(base64Data); // convert base64 to blob
|
||||
// create blob and play audio - this will throw on malformed data
|
||||
const bytes = convert_Base64_To_UInt8Array(base64Data, 'ContentReassembler.onAppendInlineAudio');
|
||||
const audioBlob = new Blob([bytes], { type: mimeType });
|
||||
const audioUrl = URL.createObjectURL(audioBlob);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Is } from '~/common/util/pwaUtils';
|
||||
import { createBlobURLFromData } from '~/common/util/urlUtils';
|
||||
import { convert_Base64WithMimeType_To_Blob } from '~/common/util/blobUtils';
|
||||
import { resizeBase64ImageIfNeeded } from '~/common/util/imageUtils';
|
||||
|
||||
import { _addDBAsset, gcDBAssetsByScope, getDBAsset } from './dblobs.db';
|
||||
@@ -67,9 +67,14 @@ export async function getImageAsset(id: DBlobAssetId) {
|
||||
|
||||
export async function getImageAssetAsBlobURL(id: DBlobAssetId) {
|
||||
const imageAsset = await getImageAsset(id);
|
||||
if (imageAsset)
|
||||
return createBlobURLFromData(imageAsset.data.base64, imageAsset.data.mimeType);
|
||||
return null;
|
||||
if (!imageAsset) return null;
|
||||
try {
|
||||
const imageBlob = await convert_Base64WithMimeType_To_Blob(imageAsset.data.base64, imageAsset.data.mimeType, 'getImageAssetAsBlobURL');
|
||||
return URL.createObjectURL(imageBlob);
|
||||
} catch (error) {
|
||||
console.warn('[DEV] getImageAssetAsBlobURL: Failed to convert image data to Blob.', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// export async function getImageAssetAsDataURL(id: DBlobAssetId) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AudioLivePlayer } from '~/common/util/audio/AudioLivePlayer';
|
||||
import { AudioPlayer } from '~/common/util/audio/AudioPlayer';
|
||||
import { CapabilityElevenLabsSpeechSynthesis } from '~/common/components/useCapabilities';
|
||||
import { apiStream } from '~/common/util/trpc.client';
|
||||
import { base64ToArrayBuffer } from '~/common/util/urlUtils';
|
||||
import { convert_Base64_To_UInt8Array } from '~/common/util/blobUtils';
|
||||
import { useUIPreferencesStore } from '~/common/stores/store-ui';
|
||||
|
||||
import { getElevenLabsData, useElevenLabsData } from './store-module-elevenlabs';
|
||||
@@ -57,13 +57,15 @@ export async function elevenLabsSpeakText(text: string, voiceId: string | undefi
|
||||
if (!liveAudioPlayer)
|
||||
liveAudioPlayer = new AudioLivePlayer();
|
||||
|
||||
const chunkBuffer = base64ToArrayBuffer(piece.audioChunk.base64);
|
||||
liveAudioPlayer.enqueueChunk(chunkBuffer);
|
||||
// enqueue a decoded audio chunk - this will throw on malformed base64 data
|
||||
const chunkArray = convert_Base64_To_UInt8Array(piece.audioChunk.base64, 'elevenLabsSpeakText (chunk)')
|
||||
liveAudioPlayer.enqueueChunk(chunkArray.buffer);
|
||||
|
||||
} else if (piece.audio) {
|
||||
|
||||
// also consieder mergin LiveAudioPlayer into AudioPlayer
|
||||
void AudioPlayer.playBuffer(base64ToArrayBuffer(piece.audio.base64)); // fire/forget - it's a single piece of audio (could be long tho)
|
||||
// also consider merging LiveAudioPlayer into AudioPlayer - note this will throw on malformed base64 data
|
||||
const audioArray = convert_Base64_To_UInt8Array(piece.audio.base64, 'elevenLabsSpeakText');
|
||||
void AudioPlayer.playBuffer(audioArray.buffer); // fire/forget - it's a single piece of audio (could be long tho)
|
||||
|
||||
} else if (piece.errorMessage)
|
||||
console.log('ElevenLabs issue:', piece.errorMessage);
|
||||
|
||||
Reference in New Issue
Block a user