fix: wav format audio, #2317

This commit is contained in:
jialin
2025-07-16 13:06:01 +08:00
parent f4d6abace7
commit 14d60264c7
9 changed files with 68 additions and 24 deletions
+22 -1
View File
@@ -1,7 +1,8 @@
import { UploadOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Tooltip, Upload } from 'antd';
import { Button, Tooltip, Upload, message } from 'antd';
import React from 'react';
import { convertFileSize } from '../../utils';
interface UploadAudioProps {
accept?: string;
@@ -10,17 +11,36 @@ interface UploadAudioProps {
icon?: React.ReactNode;
size?: 'small' | 'middle' | 'large';
shape?: 'circle' | 'round' | 'default';
maxFileSize?: number; // in bytes
onChange?: (data: { file: any; fileList: any[] }) => void;
}
const UploadAudio: React.FC<UploadAudioProps> = (props) => {
const [messageApi, contextHolder] = message.useMessage();
const { icon, accept, type, size = 'large', shape = 'circle' } = props;
const intl = useIntl();
const beforeUpload = (file: any) => {
return false;
};
const isFileSizeValid = (file: File) => {
if (props.maxFileSize && file.size > props.maxFileSize) {
messageApi.open({
type: 'warning',
content: intl.formatMessage(
{ id: 'playground.uploadfile.sizeError' },
{ size: `${convertFileSize(props.maxFileSize)}` } // Convert bytes to MB
)
});
return false;
}
return true;
};
const handleOnChange = (data: { file: any; fileList: any }) => {
if (!isFileSizeValid(data.file)) {
return;
}
props.onChange?.(data);
};
@@ -57,6 +77,7 @@ const UploadAudio: React.FC<UploadAudioProps> = (props) => {
></Button>
</div>
</Upload>
{contextHolder}
</Tooltip>
);
};
+3 -1
View File
@@ -154,5 +154,7 @@ export default {
'If the expected model isnt showing up, make sure its running and correctly categorized. If the category is incorrect, you can manually adjust it in the models settings.',
'playground.rerank.query.validate': 'The query is required.',
'playground.image.generate.error':
'Something went wrong. The image could not be generated.'
'Something went wrong. The image could not be generated.',
'playground.uploadfile.sizeError':
'File size exceeds the limit. Maximum allowed: {size}.'
};
+5 -2
View File
@@ -157,10 +157,13 @@ export default {
'期待するモデルが表示されない場合は、モデルが実行中で正しく分類されていることを確認してください。カテゴリが間違っている場合は、モデルの設定で手動で調整できます。',
'playground.rerank.query.validate': 'The query is required.',
'playground.image.generate.error':
'Something went wrong. The image could not be generated.'
'Something went wrong. The image could not be generated.',
'playground.uploadfile.sizeError':
'File size exceeds the limit. Maximum allowed: {size}.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'playground.rerank.query.validate': 'The query is required.'
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.'
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.',
// 3. 'playground.uploadfile.sizeError': 'File size exceeds the limit. Maximum allowed: {size}.'
// ========== End of To-Do List ==========
+5 -2
View File
@@ -151,10 +151,13 @@ export default {
'Если нужная модель не отображается, убедитесь, что она запущена и ей присвоена правильная категория. Если категория указана неверно, её можно изменить вручную в настройках модели.',
'playground.rerank.query.validate': 'The query is required.',
'playground.image.generate.error':
'Something went wrong. The image could not be generated.'
'Something went wrong. The image could not be generated.',
'playground.uploadfile.sizeError':
'File size exceeds the limit. Maximum allowed: {size}.'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'playground.rerank.query.validate': 'The query is required.'
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.'
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.',
// 3. 'playground.uploadfile.sizeError': 'File size exceeds the limit. Maximum allowed: {size}.'
// ========== End of To-Do List ==========
+2 -1
View File
@@ -147,5 +147,6 @@ export default {
'playground.model.noavailable.tips2':
'若预期的模型未显示,请检查模型是否已正常运行并被正确分类。如分类不正确,请编辑模型并手动调整其类别。',
'playground.rerank.query.validate': '查询内容不能为空',
'playground.image.generate.error': '出了一点问题,图片未能生成。'
'playground.image.generate.error': '出了一点问题,图片未能生成。',
'playground.uploadfile.sizeError': '上传的文件大小超过限制,最大允许 {size}'
};
@@ -2,7 +2,11 @@ import SimpleAudio from '@/components/audio-player/simple-audio';
import IconFont from '@/components/icon-font';
import UploadAudio from '@/components/upload-audio';
import HotKeys, { KeyMap } from '@/config/hotkeys';
import { convertFileToBase64, readAudioFile } from '@/utils/load-audio-file';
import {
audioTypeMap,
convertFileToBase64,
readAudioFile
} from '@/utils/load-audio-file';
import {
ClearOutlined,
CustomerServiceOutlined,
@@ -28,12 +32,6 @@ import '../style/message-input.less';
import ThumbImg from './thumb-img';
import UploadImg from './upload-img';
const audioTypeMap: Record<string, string> = {
'audio/wav': 'wav',
'audio/mp3': 'mp3',
'audio/mpeg': 'mp3'
};
const AudioWrapper = styled.div`
padding-block: 10px;
height: max-content;
@@ -303,7 +301,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
try {
const base64Audio = await convertFileToBase64(data.file);
const audioData = await readAudioFile(data.file);
console.log('audioData====', message.imgs);
console.log('audioData====', audioData, message.imgs);
setMessage((pre) => {
return {
...pre,
@@ -421,6 +419,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
)}
{actions.includes('upload') && message.role === Roles.User && (
<UploadAudio
maxFileSize={1024 * 1024}
type="text"
accept={'.mp3,.wav'}
size="middle"
@@ -1,6 +1,10 @@
import CopyButton from '@/components/copy-button';
import UploadAudio from '@/components/upload-audio';
import { convertFileToBase64, readAudioFile } from '@/utils/load-audio-file';
import {
audioTypeMap,
convertFileToBase64,
readAudioFile
} from '@/utils/load-audio-file';
import {
CustomerServiceOutlined,
EditOutlined,
@@ -18,12 +22,6 @@ import {
} from '../../config/types';
import UploadImg from '../upload-img';
const audioTypeMap: Record<string, string> = {
'audio/wav': 'wav',
'audio/mp3': 'mp3',
'audio/mpeg': 'mp3'
};
interface MessageActionsProps {
data: MessageItem;
actions: MessageItemAction[];
@@ -88,6 +86,7 @@ const MessageActions: React.FC<MessageActionsProps> = ({
{actions.includes('upload') && data.role === Roles.User && (
<UploadAudio
type="text"
maxFileSize={1024 * 1024}
accept={'.mp3,.wav'}
size="small"
shape="default"
+4 -2
View File
@@ -28,12 +28,14 @@ export const convertFileSize = (
): string | number => {
if (!sizeInBytes) return allowEmpty ? '' : 0;
const fmt = 1024;
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
let size = sizeInBytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
while (size >= fmt && unitIndex < units.length - 1) {
size /= fmt;
unitIndex++;
}
+14
View File
@@ -1,5 +1,13 @@
import { message } from 'antd';
import { convertFileSize } from './index';
export const audioTypeMap: Record<string, string> = {
'audio/wav': 'wav',
'audio/mp3': 'mp3',
'audio/mpeg': 'mp3',
'audio/x-wav': 'wav'
};
export const convertFileToBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
@@ -42,6 +50,12 @@ export const loadAudioData = async (
audio.addEventListener('ended', () => {
URL.revokeObjectURL(audio.src);
});
audio.addEventListener('error', () => {
URL.revokeObjectURL(url);
message.error('Failed to load audio metadata invalid file');
reject(new Error('Failed to load audio metadata invalid file'));
});
} catch (error) {
console.log('error====', error);
reject(error);