Merge branch 'develop' of http://25.13.9.101:9000/K17_AITS/tra-app into develop

This commit is contained in:
杨航
2025-12-09 08:45:40 +08:00
171 changed files with 511 additions and 81 deletions
@@ -133,18 +133,10 @@
URL.revokeObjectURL(blobUrl);
const mediaStream = new MediaStream();
} else if (os === 'iOS') {
console.log('是iOS');
audioContext = new AudioContext();
// 加载并初始化AudioWorklet
await audioContext.audioWorklet.addModule('static/dist/processor.worklet.js');
await audioContext.audioWorklet.addModule('static/js/processor.worklet.js');
}
mediaStream = await navigator.mediaDevices.getUserMedia({
audio: {
sampleRate: options.sampleRate,
+55 -9
View File
@@ -16,10 +16,10 @@
import { ref, onUnmounted, watch, onMounted } from 'vue';
const isStop = ref(false);
const currentPCMChunk = ref(false);
const audioOutput = ref('');
const audioOutput = ref('earpiece');
// 响应式状态
const isPlaying = ref(false); // 是否正在播放
const volume = ref(); // 播放音量(0~1
const volume = ref(1); // 播放音量(0~1
const playPCM = (pcmData) => {
if (!pcmData || pcmData.byteLength === 0) return;
currentPCMChunk.value = pcmData;
@@ -42,7 +42,55 @@
<script module="renderJS" lang="renderjs">
import { StreamPlayer } from "../js/StreamPlayer";
let player = null;
/**
* 音频路由兼容方案(适配 H5/小程序/不支持 setAudioRoute 的设备)
* @param {string} type - earpiece(听筒)/speaker(扬声器)
*/
function fallbackAudioRoute(type) {
// 1. 通用:创建音频上下文(Web Audio API),控制输出设备
try {
const AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
const audioCtx = new AudioContext();
// 针对听筒:降低音量+强制单声道(模拟听筒效果)
if (type === 'earpiece') {
audioCtx.listener.setPosition(0, 0, 0); // 定位到听筒
// 若有播放节点,设置音量为 0.3(听筒音量)
if (window.audioSource) {
window.audioSource.gain.value = 0.3;
}
} else {
// 扬声器:恢复音量+立体声
if (window.audioSource) {
window.audioSource.gain.value = 1;
}
}
}
} catch (e) {}
// 2. 安卓 H5 特殊处理:通过 Audio 对象的 speakerphone 属性(部分浏览器支持)
const audio = new Audio();
if (audio.setSpeakerphoneOn) {
// 听筒:关闭扬声器;扬声器:打开
audio.setSpeakerphoneOn(type !== 'earpiece');
audio.play(); // 触发设置生效
audio.pause(); // 无需播放实际音频
}
// 3. 小程序端(如微信小程序):调用小程序原生 API
if (wx && wx.setAudioRoute) {
// 微信小程序专属:切换音频输出(需基础库 2.10.0+)
wx.setAudioRoute({
route: type === 'earpiece' ? 'earpiece' : 'speaker',
success: () => console.log('小程序音频路由切换成功'),
fail: (e) => console.error('小程序路由切换失败:', e)
});
}
// 4. 兜底提示(非 5+ 环境)
console.log(`当前环境不支持强制音频路由,已模拟${type === 'earpiece' ? '听筒' : '扬声器'}效果`);
}
export default {
mounted() {
const _this = this;
@@ -54,9 +102,12 @@
pcmType: 'int', // 类型(int/float
callback: _this.callback
});
this.switchAudioOutput('speaker');
},
methods: {
// 切换音频输出(听筒/扬声器)
switchAudioOutput(type) {
console.log('切换音频输出')
},
appendPCMChunk(numArray) {
// console.log('接收到', numArray.length);
if (!numArray || numArray.length === 0) return;
@@ -65,11 +116,6 @@
const arrayBuffer = uint8.buffer;
player.appendChunk(arrayBuffer);
},
// 切换扬声器/听筒核心方法
switchAudioOutput(type) {
// plus.audio.setAudioRoute(type === 'speaker' ? 'speaker' : 'earpiece');
},
// 停止播放(销毁播放器)
stop() {
if (player) {
+2 -4
View File
@@ -60,10 +60,8 @@ export enum CompressionType {
* 控制指令枚举(配合 MessageType.CONTROL_CMD 使用)
*/
export enum ControlCommand {
HEARTBEAT = 0b0001,
PAUSE = 0b0010,
RESUME = 0b0011,
STOP = 0b0100,
START_PLAY = 0b0001, // 一句话播放开始
FINISH_PLAY = 0b0010, // 一句话播放结束
}
/**
+5 -3
View File
@@ -51,7 +51,8 @@
const dataInfo = reactive({
traId: '',
chaId: '',
type: '',
traType: '',
traInterType: '',
execId: '',
sceneDesc: '',
userName: '',
@@ -77,7 +78,7 @@
'&execId=' +
dataInfo.execId +
'&type=' +
dataInfo.type +
dataInfo.traType +
'&isPreview=' +
(dataInfo.isPreview ? '1' : '')
);
@@ -136,7 +137,8 @@
onLoad((e) => {
dataInfo.traId = e.traId ?? '';
dataInfo.chaId = e.chaId ?? '';
dataInfo.type = e.type ?? '';
dataInfo.traType = e.type ?? ''; // 陪练类型 01-练习 02-考试
dataInfo.traInterType = e.traInterType ?? '02'; // 陪练交互类型 01 对话 02 语音 03 视频
dataInfo.preview = e.isPreview === '1';
const userInfo = getUserInfo();
dataInfo.userName = userInfo.userName;
+10 -3
View File
@@ -124,9 +124,10 @@
import { ref, unref, onMounted, computed, nextTick } from 'vue';
import { onShow, onHide, onLoad, onUnload, onLaunch, onBackPress } from '@dcloudio/uni-app';
import common from '@/common/common';
import {getPhoneEnvBool} from '@/common/common';
import TouchBtn from './components/touchBtn.vue';
import ImagePreview from '@/components/image-preview/image-preview.vue';
import { commonUploadVoiceFile } from '@/api/common.js';
import { commonUploadVoiceFile} from '@/api/common.js';
import { queryTraPartnerCharacterInfoById, partnerChatReportTrigger } from '@/api/sparring.js';
import { useSocketStore } from '@/store/socket.js';
import { useStorageStore } from '@/store/storage.js';
@@ -240,9 +241,15 @@
};
const toTalking = async () => {
try {
await initRecord();
console.log('权限状态');
console.log('申请权限',getPhoneEnvBool('AND'));
if(getPhoneEnvBool('AND')){
console.log('申请权限');
// await initRecord();
}
common.setPageCache('tipMsgsceneDesc', {
sceneDesc: detailInfo.value.sceneDesc
});