stream-chat-react
Version:
React components to create chat conversations or livestream style chat
1 lines • 8.08 kB
Source Map (JSON)
{"version":3,"file":"audioProcessing.766ca76c.mjs","names":[],"sources":["../../src/components/ReactFileUtilities/utils.ts","../../src/components/MediaRecorder/transcode/audioProcessing.ts"],"sourcesContent":["import type { FileLike, RecordedMediaType } from './types';\nimport type { ChangeEvent } from 'react';\nimport { useCallback } from 'react';\n\nexport const useHandleFileChangeWrapper = (\n resetOnChange = false,\n handler?: (files: Array<File>) => void,\n) =>\n useCallback(\n ({ currentTarget }: ChangeEvent<HTMLInputElement>) => {\n const { files } = currentTarget;\n\n if (!files) return;\n\n try {\n handler?.(Array.from(files));\n } catch (error) {\n console.error(error);\n }\n\n if (resetOnChange) currentTarget.value = '';\n },\n [handler, resetOnChange],\n );\n\nexport function dataTransferItemsHaveFiles(items?: DataTransferItem[]): boolean {\n if (!items || !items.length) {\n return false;\n }\n for (const item of items) {\n if (item.kind === 'file' || item.type === 'text/html') {\n return true;\n }\n }\n return false;\n}\n\nexport async function dataTransferItemsToFiles(\n items?: DataTransferItem[],\n): Promise<FileLike[]> {\n if (!items || !items.length) {\n return [];\n }\n\n // If there are files inside the DataTransferItem prefer those\n const fileLikes = getFileLikes(items);\n if (fileLikes.length) {\n return fileLikes;\n }\n\n // Otherwise extract images from html\n const blobPromises = [];\n for (const item of items) {\n if (item.type === 'text/html') {\n blobPromises.push(\n new Promise<void>((accept) => {\n item.getAsString(async (s) => {\n const imagePromises = extractImageSources(s).map((src) =>\n getImageSource(fileLikes, src),\n );\n\n await Promise.all(imagePromises);\n accept();\n });\n }),\n );\n }\n }\n await Promise.all(blobPromises);\n return fileLikes;\n}\n\nfunction getFileLikes(items: DataTransferItem[]) {\n const fileLikes = [];\n for (const item of items) {\n if (item.kind === 'file') {\n const file = item.getAsFile();\n if (file) {\n fileLikes.push(file);\n }\n }\n }\n return fileLikes;\n}\n\nasync function getImageSource(fileLikes: FileLike[], src: string) {\n let res;\n try {\n res = await fetch(src);\n } catch (e) {\n return;\n }\n const contentType = res.headers.get('Content-type') || 'application/octet-stream';\n const buf = await res.arrayBuffer();\n const blob = new Blob([buf], { type: contentType });\n fileLikes.push(blob);\n}\n\nconst extractImageSources = (s: string) => {\n const imageTags = new DOMParser()\n .parseFromString(s, 'text/html')\n .getElementsByTagName('img');\n return Array.from(imageTags, (tag) => tag.src).filter((tag) => tag);\n};\n\nexport const isBlobButNotFile = (obj: unknown): obj is Blob =>\n obj instanceof Blob && !(obj instanceof File);\n\nexport const createFileFromBlobs = ({\n blobsArray,\n fileName,\n mimeType,\n}: {\n blobsArray: Blob[];\n fileName: string;\n mimeType: string;\n}) => {\n const concatenatedBlob = new Blob(blobsArray, { type: mimeType });\n return new File([concatenatedBlob], fileName, { type: concatenatedBlob.type });\n};\n\nexport const getExtensionFromMimeType = (mimeType: string) => {\n const match = mimeType.match(/\\/([^/;]+)/);\n return match && match[1];\n};\n\nexport const getRecordedMediaTypeFromMimeType = (\n mimeType: string,\n): RecordedMediaType | null => {\n const match = mimeType.match(/^(audio|video)\\/.*$/);\n return match && (match[1] as RecordedMediaType);\n};\n\nexport const readFileAsArrayBuffer = (file: File): Promise<ArrayBuffer> =>\n new Promise((resolve, reject) => {\n const fileReader = new FileReader();\n fileReader.onload = () => {\n resolve(fileReader.result as ArrayBuffer);\n };\n\n fileReader.onerror = () => {\n reject(fileReader.error);\n };\n\n fileReader.readAsArrayBuffer(file);\n });\n\nexport const generateFileName = (mimeType: string) =>\n `file_${new Date().toISOString()}.${getExtensionFromMimeType(mimeType)}`;\n","import { readFileAsArrayBuffer } from '../../ReactFileUtilities';\n\n/**\n * In the context of resampling audio data, AudioContext is used to decode the input audio file into an AudioBuffer,\n * which is a fundamental data structure representing audio data.\n * @param file\n */\nexport const toAudioBuffer = async (file: File) => {\n const audioCtx = new AudioContext();\n\n const arrayBuffer = await readFileAsArrayBuffer(file);\n const decodedData = await audioCtx.decodeAudioData(arrayBuffer);\n if (audioCtx.state !== 'closed') await audioCtx.close();\n return decodedData;\n};\n\n/**\n * OfflineAudioContext is a specialized type of AudioContext that does not render audio in real-time and is used for offline audio processing tasks.\n * It allows performing audio processing and rendering without actually playing the audio through speakers or outputting it to a destination.\n * In the context of resampling audio data, OfflineAudioContext is used to resample the decoded AudioBuffer from a file to the desired sample rate.\n * It provides more flexibility and control over audio processing, as it can operate at different sample rates and durations compared to real-time audio contexts.\n * @param audioBuffer\n * @param sampleRate\n */\nexport const renderAudio = async (audioBuffer: AudioBuffer, sampleRate: number) => {\n const offlineAudioCtx = new OfflineAudioContext(\n audioBuffer.numberOfChannels,\n audioBuffer.duration * sampleRate,\n sampleRate,\n );\n const source = offlineAudioCtx.createBufferSource();\n source.buffer = audioBuffer;\n source.connect(offlineAudioCtx.destination);\n source.start();\n\n return await offlineAudioCtx.startRendering();\n};\n"],"mappings":"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"}