JLBA202505130001_关于吉林银行新建AI智能培训系统的需求_完善流式语音代码
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
+1
-1
@@ -50,7 +50,7 @@
|
||||
"vue-i18n": "^9.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.4.8",
|
||||
"@dcloudio/types": "^3.4.29",
|
||||
"@dcloudio/uni-automator": "3.0.0-4060620250520001",
|
||||
"@dcloudio/uni-cli-shared": "3.0.0-4060620250520001",
|
||||
"@dcloudio/uni-stacktracey": "3.0.0-4060620250520001",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// components/touch-btn/touch-btn.images.ts
|
||||
// 统一导出所有需要的图片资源
|
||||
export { default as cancelBtn } from '@/static/images/course/cancel.png';
|
||||
export { default as cancelActiveBtn } from '@/static/images/course/cancel-active.png';
|
||||
export { default as translateBtn } from '@/static/images/course/translate.png';
|
||||
export { default as translateActiveBtn } from '@/static/images/course/translate-active.png';
|
||||
@@ -0,0 +1,15 @@
|
||||
import { get_base_url } from '@/api/request.js';
|
||||
// const url = '/trapractice/voiceCallSocket/voiceCall'
|
||||
// const url = '/traapp/voiceTransSocket/open';
|
||||
const url = '/traapp/voiceAiModelSocket/open';
|
||||
const _baseUrl = get_base_url(url).split('http').join('ws');
|
||||
export const wsUrl = _baseUrl + url;
|
||||
const windowInfo = uni.getWindowInfo();
|
||||
// 安全区域信息
|
||||
const safeArea = windowInfo.safeArea;
|
||||
// 按钮高度
|
||||
const btnHeight = (windowInfo.screenWidth / 750) * 234;
|
||||
// 按钮的顶部边界
|
||||
export const bottomAreaTopBoundary = safeArea.bottom - btnHeight;
|
||||
// 屏幕横向分割线
|
||||
export const horizontalSplitX = safeArea.right / 2;
|
||||
@@ -0,0 +1 @@
|
||||
export type StatusType = 'voice' | 'input' | 'text';
|
||||
@@ -89,27 +89,22 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import cancelBtn from '@/static/images/course/cancel.png';
|
||||
import cancelActiveBtn from '@/static/images/course/cancel-active.png';
|
||||
import translateBtn from '@/static/images/course/translate.png';
|
||||
import translateActiveBtn from '@/static/images/course/translate-active.png';
|
||||
<script setup lang="ts">
|
||||
// 导出图片
|
||||
import { cancelBtn, cancelActiveBtn, translateBtn, translateActiveBtn } from './touch-btn.images';
|
||||
import { StatusType } from './touch-btn.types';
|
||||
import { wsUrl, bottomAreaTopBoundary, horizontalSplitX } from './touch-btn';
|
||||
import { ref, computed, onMounted, nextTick, watch, reactive } from 'vue';
|
||||
import common from '@/common/common';
|
||||
import { onHide } from '@dcloudio/uni-app';
|
||||
import permission from '@/common/permission.js';
|
||||
import { getPhoneEnvBool } from '@/common/common.js';
|
||||
import { initRecord } from '@/composables/useExamSubject.js';
|
||||
import { getToken } from '@/common/common';
|
||||
import { getPhoneEnvBool, getToken } from '@/common/common.js';
|
||||
import { startAudioRecord, stopAudioRecord } from '@/uni_modules/ty-recording';
|
||||
import { get_base_url } from '@/api/request.js';
|
||||
import { ProtocolCodec, MessageType, ControlCommand,ControlCode } from '@/pages/sparring/js/ProtocolCodec';
|
||||
// const url = '/trapractice/voiceCallSocket/voiceCall'
|
||||
// const url = '/traapp/voiceTransSocket/open';
|
||||
const url = '/traapp/voiceAiModelSocket/open';
|
||||
const _baseUrl = get_base_url(url).split('http').join('ws');
|
||||
import { ProtocolCodec, MessageType, ControlCommand, ControlCode } from '@/pages/sparring/js/ProtocolCodec';
|
||||
import permissionApi from '@/common/permission';
|
||||
|
||||
const emit = defineEmits(['submit']);
|
||||
const ws = ref(null);
|
||||
const status = ref<StatusType>('voice');
|
||||
const props = defineProps({
|
||||
isDisabled: {
|
||||
default: false,
|
||||
@@ -147,15 +142,11 @@
|
||||
});
|
||||
// 记录 按下移动位置
|
||||
const touchPos = reactive({ x: 0, y: 0 });
|
||||
const windowInfo = uni.getWindowInfo();
|
||||
// 安全区域信息
|
||||
const safeArea = windowInfo.safeArea;
|
||||
console.log('safeArea', safeArea);
|
||||
|
||||
// 计算是否超出按下盒子位置01代表下方盒子,02代表左上03代表右上
|
||||
const isOutStatus = computed(() => {
|
||||
const btnHeight = (windowInfo.screenWidth / 750) * 234;
|
||||
if (touchPos.y < safeArea.bottom - btnHeight) {
|
||||
if (touchPos.x < safeArea.right / 2) return '02';
|
||||
if (touchPos.y < bottomAreaTopBoundary) {
|
||||
if (touchPos.x < horizontalSplitX) return '02';
|
||||
else return '03';
|
||||
} else {
|
||||
return '01';
|
||||
@@ -175,16 +166,20 @@
|
||||
const popupRef = ref(null);
|
||||
const inputText = ref('');
|
||||
let startTime = 0;
|
||||
|
||||
const startTimer = ref(null); // 延迟启动的定时器ID
|
||||
const startFlag = ref(1);
|
||||
// 开启语音
|
||||
const startRecord = async (obj) => {
|
||||
try {
|
||||
await permissionApi.judgeIosPermission('record');
|
||||
} catch (e) {
|
||||
console.error('麦克风权限申请失败:', e);
|
||||
return;
|
||||
}
|
||||
|
||||
const changedTouche = obj.touches[0];
|
||||
touchPos.x = changedTouche.clientX;
|
||||
touchPos.y = changedTouche.clientY;
|
||||
const wsUrl = _baseUrl + url + '?summary=' + getToken();
|
||||
ws.value = uni.connectSocket({
|
||||
url: wsUrl,
|
||||
url: wsUrl + '?summary=' + getToken(),
|
||||
fail: () => {},
|
||||
success: () => {}
|
||||
});
|
||||
@@ -192,21 +187,22 @@
|
||||
console.log('ws已连接');
|
||||
popupRef.value.open();
|
||||
startAudioRecord({
|
||||
onFrame:(pcmData) => {
|
||||
// pcmData 是ByteArray类型的原始音频数据
|
||||
console.log('采集到音频数据长度1:', pcmData.length);
|
||||
onFrame: (pcmData) => {
|
||||
ws.value.send({
|
||||
data: ProtocolCodec.pack(MessageType.AUDIO_DATA, pcmData)
|
||||
});
|
||||
// 可在此处将PCM转Base64/编码为MP3等,或直接传输
|
||||
},
|
||||
onStop:(pcmData) => {
|
||||
onStart: ({ startTime }) => {
|
||||
console.log('开始', startTime);
|
||||
},
|
||||
onStop: () => {
|
||||
console.log('关闭');
|
||||
},
|
||||
onError:(err) => {
|
||||
console.log('err', err.errMsg);
|
||||
console.log('err', err.errCode);
|
||||
},
|
||||
onError: ({ errCode, errMsg }) => {
|
||||
if (errCode === 9010001) {
|
||||
console.log(errMsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
ws.value.onError((err) => {
|
||||
@@ -216,17 +212,20 @@
|
||||
console.log('onClose', err);
|
||||
});
|
||||
ws.value.onMessage((res) => {
|
||||
const { msgType, body } = ProtocolCodec.unpack(res.data);
|
||||
console.log('来消息了', msgType, body);
|
||||
if (msgType === MessageType.TEXT_MESSAGE) {
|
||||
tempText.value = '';
|
||||
allText.value = allText.value + body;
|
||||
} else if (msgType === MessageType.TIP_MESSAGE) {
|
||||
tempText.value = body;
|
||||
try {
|
||||
const { msgType, body } = ProtocolCodec.unpack(res.data);
|
||||
console.log('来消息了', msgType, body);
|
||||
if (msgType === MessageType.TEXT_MESSAGE) {
|
||||
tempText.value = '';
|
||||
allText.value = allText.value + body;
|
||||
} else if (msgType === MessageType.TIP_MESSAGE) {
|
||||
tempText.value = body;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('后端发来的信息有问题');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 关掉遮罩层
|
||||
const closePopup = () => {
|
||||
nextTick(() => {
|
||||
@@ -234,19 +233,21 @@
|
||||
tempText.value = '';
|
||||
popupRef.value.close();
|
||||
});
|
||||
ws.value.close({
|
||||
code: 1000,
|
||||
reason: '挂断',
|
||||
success: () => {
|
||||
console.log('挂断success');
|
||||
},
|
||||
fail: () => {
|
||||
console.log('挂断fail');
|
||||
},
|
||||
complete: () => {
|
||||
console.log('挂断complete');
|
||||
}
|
||||
});
|
||||
|
||||
ws.value &&
|
||||
ws.value.close({
|
||||
code: 1000,
|
||||
reason: '挂断',
|
||||
success: () => {
|
||||
console.log('挂断success');
|
||||
},
|
||||
fail: () => {
|
||||
console.log('挂断fail');
|
||||
},
|
||||
complete: () => {
|
||||
console.log('挂断complete');
|
||||
}
|
||||
});
|
||||
};
|
||||
// 松开按钮
|
||||
const loosenButton = () => {
|
||||
@@ -255,7 +256,7 @@
|
||||
// 03转文字
|
||||
console.log('已发送', '03转文字');
|
||||
ws.value.send({
|
||||
data: ProtocolCodec.pack(MessageType.CONTROL_CMD, {type:ControlCode.FRNOT_TO_SERVER_OVER})
|
||||
data: ProtocolCodec.pack(MessageType.CONTROL_CMD, { type: ControlCode.FRNOT_TO_SERVER_OVER })
|
||||
});
|
||||
} else {
|
||||
closePopup();
|
||||
@@ -273,10 +274,8 @@
|
||||
} else if (isOutStatus.value === '03') {
|
||||
// 03转文字
|
||||
}
|
||||
|
||||
|
||||
stopAudioRecord();
|
||||
|
||||
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
</uv-checkbox-group>
|
||||
<view class="ysxy_tip font_pf">
|
||||
已阅读并同意
|
||||
|
||||
<span class="ysxy_term" @click="common.navigateTo('/pages/login/ysxy?page=1')">《用户隐私协议》</span>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -275,9 +275,19 @@ export class ProtocolCodec {
|
||||
}
|
||||
|
||||
// 2. 拆分头部和包体
|
||||
const header = uint8Packet.subarray(0, ProtocolConst.HEADER_SIZE);
|
||||
const bodyBuffer = uint8Packet.subarray(ProtocolConst.HEADER_SIZE);
|
||||
|
||||
// const header = uint8Packet.subarray(0, ProtocolConst.HEADER_SIZE);
|
||||
// const bodyBuffer = uint8Packet.subarray(ProtocolConst.HEADER_SIZE);
|
||||
let header: Uint8Array, bodyBuffer: Uint8Array;
|
||||
try {
|
||||
header = uint8Packet.subarray(0, ProtocolConst.HEADER_SIZE);
|
||||
bodyBuffer = uint8Packet.subarray(ProtocolConst.HEADER_SIZE);
|
||||
} catch (e) {
|
||||
// 捕获subarray调用异常,并抛出更易理解的错误信息
|
||||
const error = e as Error;
|
||||
throw new Error(
|
||||
`解包拆分头部/包体失败:${error.message},原始包类型=${packet.constructor.name},长度=${uint8Packet.length}字节`
|
||||
);
|
||||
}
|
||||
// 3. 解析头部字段
|
||||
// 字节0:消息类型(高4位) + 协议版本(低4位)
|
||||
const byte0 = header[0];
|
||||
|
||||
Vendored
-20
@@ -1,20 +0,0 @@
|
||||
// 声明图片文件模块
|
||||
declare module '*.jpg' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.jpeg' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
|
||||
declare module '*.gif' {
|
||||
const src: string;
|
||||
export default src;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StartAudioRecordOptions } from '../interface.uts';
|
||||
import { StartAudioRecordFailImpl,AudioErrorCode } from '../unierror.uts';
|
||||
import { StartAudioRecordOptions, AudioStartRes } from '../interface.uts';
|
||||
import { StartAudioRecordFailImpl } from '../unierror.uts';
|
||||
|
||||
/**
|
||||
* 引用Android音频相关系统库
|
||||
@@ -26,7 +26,6 @@ let recordThread : Thread | null = null;
|
||||
// ========== 2. 对外暴露的便捷方法(符合UTS导出规范) ==========
|
||||
@UTSJS.keepAlive
|
||||
export function startAudioRecord(options : StartAudioRecordOptions) : void {
|
||||
console.log('启动', isRecording.get());
|
||||
if (isRecording.get()) return; // 避免重复启动
|
||||
const _audioRecord = new AudioRecord(
|
||||
MediaRecorder.AudioSource.MIC,
|
||||
@@ -35,18 +34,19 @@ export function startAudioRecord(options : StartAudioRecordOptions) : void {
|
||||
audioFormat,
|
||||
bufferSize
|
||||
);
|
||||
|
||||
if (_audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
|
||||
|
||||
const err = new StartAudioRecordFailImpl(AudioErrorCode.AUDIO_FORMAT_ILLEGAL);
|
||||
const err = new StartAudioRecordFailImpl(9010001);
|
||||
options.onError?.(err);
|
||||
return;
|
||||
}
|
||||
|
||||
audioRecord = _audioRecord;
|
||||
isRecording.set(true)
|
||||
const _recordThread = new Thread(() => {
|
||||
_audioRecord.startRecording(); // 开始采集
|
||||
|
||||
options.onStart?.({
|
||||
startTime:1111111
|
||||
} as AudioStartRes);
|
||||
console.log('AudioRecord已启动采集');
|
||||
const buffer = new ByteArray(bufferSize); // 缓冲区只创建一次,避免重复分配内存
|
||||
while (isRecording.get()) {
|
||||
@@ -95,4 +95,5 @@ export function stopAudioRecord() : void {
|
||||
recordThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
* uts插件接口定义文件,按规范定义接口文件可以在HBuilderX中更好的做到语法提示
|
||||
*/
|
||||
|
||||
import { AudioErrorCode } from "./unierror.uts"
|
||||
|
||||
// 成功开启录音的回调参数:返回录音基础配置
|
||||
export type AudioStartRes = {
|
||||
recordId : string; // 录音唯一标识(方便多录音实例管理)
|
||||
sampleRate : number; // 采样率(如16000)
|
||||
format : string; // 录音格式(如pcm/mp3)
|
||||
recordId ?: string; // 录音唯一标识(方便多录音实例管理)
|
||||
sampleRate ?: number; // 采样率(如16000)
|
||||
format ?: string; // 录音格式(如pcm/mp3)
|
||||
startTime : number; // 开启时间戳(毫秒)
|
||||
};
|
||||
|
||||
@@ -29,7 +28,7 @@ export type AudioFileRes = {
|
||||
* - 9010001 错误信息1
|
||||
* - 9010002 错误信息2
|
||||
*/
|
||||
// export type AudioErrorCode = 9010001 | 9010002;
|
||||
export type AudioErrorCode = 9010001 | 9010002;
|
||||
|
||||
/**
|
||||
* 录音错误的回调参数:带错误码+错误信息,方便问题定位
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
|
||||
import { AudioErrorRes } from "./interface.uts"
|
||||
import { AudioErrorRes, AudioErrorCode } from "./interface.uts"
|
||||
/**
|
||||
* 错误主题
|
||||
* 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
|
||||
@@ -7,138 +7,77 @@ import { AudioErrorRes } from "./interface.uts"
|
||||
*/
|
||||
export const UniErrorSubject = 'ty-recording';
|
||||
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
* @UniError
|
||||
*/
|
||||
/**
|
||||
* 音频录制错误码枚举
|
||||
* 音频录制错误码-错误信息映射表(硬编码版本)
|
||||
* 前缀901:专属音频模块错误码
|
||||
* 分段规则:9010001-9010009(权限)、9010010-9010019(初始化)、9010020-9010029(采集)、9010030-9010039(线程)、9010040-9010049(资源)、9010050-9010059(参数)、9010060-9010069(系统/硬件)、9010070+(预留)
|
||||
* @UniError
|
||||
*/
|
||||
export const AudioErrorCode = {
|
||||
export const AudioErrors = new Map<AudioErrorCode, string>([
|
||||
// 权限相关(9010001-9010009)
|
||||
MIC_PERMISSION_NONE: 9010001, // 麦克风权限未授予
|
||||
MIC_PERMISSION_DENIED: 9010002, // 麦克风权限被永久拒绝
|
||||
MIC_PERMISSION_GET_FAIL: 9010003,// 获取麦克风权限状态失败
|
||||
[9010001, '麦克风权限未授予,请前往设置开启'],
|
||||
[9010002, '麦克风权限被永久拒绝,请前往设置开启'],
|
||||
[9010003, '获取麦克风权限状态失败'],
|
||||
|
||||
// 初始化相关(9010010-9010019)
|
||||
AUDIO_RECORD_INIT_FAIL: 9010010, // AudioRecord实例初始化失败
|
||||
AUDIO_RECORD_NOT_INIT: 9010011, // AudioRecord未初始化就调用录制/停止
|
||||
AUDIO_RECORD_CREATE_FAIL: 9010012,// AudioRecord实例创建失败(系统资源不足)
|
||||
[9010010, '音频录制实例初始化失败'],
|
||||
[9010011, '音频录制实例未初始化,无法执行操作'],
|
||||
[9010012, '系统资源不足,无法创建音频录制实例'],
|
||||
|
||||
// 采集过程相关(9010020-9010029)
|
||||
RECORD_READ_DATA_FAIL: 9010020, // 音频采集读取数据失败
|
||||
RECORD_INTERRUPTED: 9010021, // 音频采集被中断(如麦克风被抢占)
|
||||
RECORD_BUFFER_EMPTY: 9010022, // 采集缓冲区无有效数据
|
||||
RECORD_START_FAIL: 9010023, // 调用startRecording启动采集失败
|
||||
[9010020, '音频采集读取数据失败'],
|
||||
[9010021, '音频采集被中断(麦克风被其他应用抢占)'],
|
||||
[9010022, '音频采集缓冲区无有效数据'],
|
||||
[9010023, '启动音频采集失败'],
|
||||
|
||||
// 线程相关(9010030-9010039)
|
||||
RECORD_THREAD_CREATE_FAIL: 9010030,// 采集线程创建失败
|
||||
RECORD_THREAD_START_FAIL: 9010031, // 采集线程启动失败
|
||||
RECORD_THREAD_INTERRUPT_FAIL: 9010032,// 采集线程中断失败
|
||||
RECORD_THREAD_CRASH: 9010033, // 采集线程运行崩溃
|
||||
[9010030, '采集线程创建失败'],
|
||||
[9010031, '采集线程启动失败'],
|
||||
[9010032, '采集线程中断失败'],
|
||||
[9010033, '采集线程运行崩溃'],
|
||||
|
||||
// 资源释放相关(9010040-9010049)
|
||||
RECORD_STOP_FAIL: 9010040, // 调用stop停止采集失败
|
||||
AUDIO_RECORD_RELEASE_FAIL: 9010041,// AudioRecord资源释放失败
|
||||
RECORD_REPEAT_RELEASE: 9010042, // 音频资源重复释放
|
||||
RECORD_RESOURCE_LEAK: 9010043, // 音频资源泄漏(未正常释放)
|
||||
[9010040, '停止音频采集失败'],
|
||||
[9010041, '音频录制资源释放失败'],
|
||||
[9010042, '音频资源重复释放'],
|
||||
[9010043, '音频资源泄漏(未正常释放)'],
|
||||
|
||||
// 参数配置相关(9010050-9010059)
|
||||
SAMPLE_RATE_NOT_SUPPORT: 9010050, // 采样率不被设备支持
|
||||
CHANNEL_CONFIG_ILLEGAL: 9010051, // 声道配置非法/不支持
|
||||
AUDIO_FORMAT_ILLEGAL: 9010052, // 音频格式非法/不支持
|
||||
BUFFER_SIZE_TOO_SMALL: 9010053, // 采集缓冲区大小过小(低于系统最小值)
|
||||
BUFFER_SIZE_ILLEGAL: 9010054, // 采集缓冲区大小配置非法
|
||||
[9010050, '当前设备不支持该采样率'],
|
||||
[9010051, '声道配置非法或不被支持'],
|
||||
[9010052, '音频格式非法或不被支持'],
|
||||
[9010053, '采集缓冲区大小低于系统最小值'],
|
||||
[9010054, '采集缓冲区大小配置非法'],
|
||||
|
||||
// 系统/硬件/外部冲突(9010060-9010069)
|
||||
MIC_OCCUPIED: 9010060, // 麦克风被其他应用占用
|
||||
AUDIO_HARDWARE_ERROR: 9010061, // 音频硬件故障
|
||||
SYSTEM_RESOURCE_INSUFFICIENT: 9010062,// 系统资源不足(无法创建音频实例)
|
||||
AUDIO_SERVICE_EXCEPTION: 9010063,// 系统音频服务异常/未启动
|
||||
[9010060, '麦克风被其他应用占用'],
|
||||
[9010061, '音频硬件故障'],
|
||||
[9010062, '系统资源不足,无法创建音频实例'],
|
||||
[9010063, '系统音频服务异常或未启动'],
|
||||
|
||||
// 通用业务异常(9010070-9010079)
|
||||
RECORD_REPEAT_START: 9010070, // 重复启动音频录制
|
||||
RECORD_NOT_RUNNING: 9010071, // 未在录制状态却调用停止/暂停
|
||||
BYTE_ARRAY_COPY_FAIL: 9010072, // 音频数据缓冲区拷贝失败
|
||||
[9010070, '重复启动音频录制'],
|
||||
[9010071, '未在录制状态,无法执行停止/暂停操作'],
|
||||
[9010072, '音频数据缓冲区拷贝失败'],
|
||||
|
||||
// 预留扩展(9010080+)
|
||||
RESERVED_01: 9010080
|
||||
}
|
||||
/**
|
||||
* 音频录制错误码-错误信息映射表
|
||||
* 使用AudioErrorCode常量作为键,避免硬编码数字,提升可维护性
|
||||
* @UniError
|
||||
*/
|
||||
export const AudioErrors = new Map<number, string>([
|
||||
// 权限相关
|
||||
[AudioErrorCode.MIC_PERMISSION_NONE, '麦克风权限未授予,请前往设置开启'],
|
||||
[AudioErrorCode.MIC_PERMISSION_DENIED, '麦克风权限被永久拒绝,请前往设置开启'],
|
||||
[AudioErrorCode.MIC_PERMISSION_GET_FAIL, '获取麦克风权限状态失败'],
|
||||
|
||||
// 初始化相关
|
||||
[AudioErrorCode.AUDIO_RECORD_INIT_FAIL, '音频录制实例初始化失败'],
|
||||
[AudioErrorCode.AUDIO_RECORD_NOT_INIT, '音频录制实例未初始化,无法执行操作'],
|
||||
[AudioErrorCode.AUDIO_RECORD_CREATE_FAIL, '系统资源不足,无法创建音频录制实例'],
|
||||
|
||||
// 采集过程相关
|
||||
[AudioErrorCode.RECORD_READ_DATA_FAIL, '音频采集读取数据失败'],
|
||||
[AudioErrorCode.RECORD_INTERRUPTED, '音频采集被中断(麦克风被其他应用抢占)'],
|
||||
[AudioErrorCode.RECORD_BUFFER_EMPTY, '音频采集缓冲区无有效数据'],
|
||||
[AudioErrorCode.RECORD_START_FAIL, '启动音频采集失败'],
|
||||
|
||||
// 线程相关
|
||||
[AudioErrorCode.RECORD_THREAD_CREATE_FAIL, '采集线程创建失败'],
|
||||
[AudioErrorCode.RECORD_THREAD_START_FAIL, '采集线程启动失败'],
|
||||
[AudioErrorCode.RECORD_THREAD_INTERRUPT_FAIL, '采集线程中断失败'],
|
||||
[AudioErrorCode.RECORD_THREAD_CRASH, '采集线程运行崩溃'],
|
||||
|
||||
// 资源释放相关
|
||||
[AudioErrorCode.RECORD_STOP_FAIL, '停止音频采集失败'],
|
||||
[AudioErrorCode.AUDIO_RECORD_RELEASE_FAIL, '音频录制资源释放失败'],
|
||||
[AudioErrorCode.RECORD_REPEAT_RELEASE, '音频资源重复释放'],
|
||||
[AudioErrorCode.RECORD_RESOURCE_LEAK, '音频资源泄漏(未正常释放)'],
|
||||
|
||||
// 参数配置相关
|
||||
[AudioErrorCode.SAMPLE_RATE_NOT_SUPPORT, '当前设备不支持该采样率'],
|
||||
[AudioErrorCode.CHANNEL_CONFIG_ILLEGAL, '声道配置非法或不被支持'],
|
||||
[AudioErrorCode.AUDIO_FORMAT_ILLEGAL, '音频格式非法或不被支持'],
|
||||
[AudioErrorCode.BUFFER_SIZE_TOO_SMALL, '采集缓冲区大小低于系统最小值'],
|
||||
[AudioErrorCode.BUFFER_SIZE_ILLEGAL, '采集缓冲区大小配置非法'],
|
||||
|
||||
// 系统/硬件/外部冲突
|
||||
[AudioErrorCode.MIC_OCCUPIED, '麦克风被其他应用占用'],
|
||||
[AudioErrorCode.AUDIO_HARDWARE_ERROR, '音频硬件故障'],
|
||||
[AudioErrorCode.SYSTEM_RESOURCE_INSUFFICIENT, '系统资源不足,无法创建音频实例'],
|
||||
[AudioErrorCode.AUDIO_SERVICE_EXCEPTION, '系统音频服务异常或未启动'],
|
||||
|
||||
// 通用业务异常
|
||||
[AudioErrorCode.RECORD_REPEAT_START, '重复启动音频录制'],
|
||||
[AudioErrorCode.RECORD_NOT_RUNNING, '未在录制状态,无法执行停止/暂停操作'],
|
||||
[AudioErrorCode.BYTE_ARRAY_COPY_FAIL, '音频数据缓冲区拷贝失败'],
|
||||
|
||||
// 预留扩展
|
||||
[AudioErrorCode.RESERVED_01, '预留错误码']
|
||||
[9010080, '预留错误码']
|
||||
]);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 错误对象实现
|
||||
*/
|
||||
export class StartAudioRecordFailImpl extends UniError implements AudioErrorRes {
|
||||
|
||||
override errCode: AudioErrorCode
|
||||
/**
|
||||
* 错误对象构造函数
|
||||
*/
|
||||
constructor(errCode : any) {
|
||||
constructor(errCode : AudioErrorCode) {
|
||||
super();
|
||||
|
||||
this.errSubject = UniErrorSubject;
|
||||
const _errCode = errCode as number
|
||||
this.errCode = _errCode;
|
||||
this.errMsg = AudioErrors.get(_errCode) as string;
|
||||
this.errCode = errCode;
|
||||
this.errMsg = AudioErrors.get(errCode) ?? "";
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Vue 项目常用配置(根据实际版本调整)
|
||||
"moduleResolution": "NodeNext", // 或 "Node"
|
||||
"module": "NodeNext", // 与 moduleResolution 保持一致
|
||||
"target": "ES2022",
|
||||
"jsx": "preserve",
|
||||
"lib": ["ES2022", "DOM"],
|
||||
"baseUrl": ".", // 表示以 tsconfig.json 所在目录为基准
|
||||
"types": ["vue"], // 确保包含 vue 类型定义
|
||||
"types": ["vue", "@dcloudio/types"],
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user