diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5db8f5a..81957ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+## [1.12.0](https://github.com/TencentCloudBase/cloudbase-agent-ui/compare/v1.11.0...v1.12.0) (2025-05-06)
+
+
+### Features
+
+* 增加倍速控制 ([99690d9](https://github.com/TencentCloudBase/cloudbase-agent-ui/commit/99690d97673423ba99e28b772962e300ce450dea))
+
+
+### Bug Fixes
+
+* fix doc ([72c6a53](https://github.com/TencentCloudBase/cloudbase-agent-ui/commit/72c6a53d226cf6426da4569be21d4bc77bba0827))
+
## [1.11.0](https://github.com/TencentCloudBase/cloudbase-agent-ui/compare/v1.10.1...v1.11.0) (2025-04-27)
diff --git a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/playing.svg b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/playing.svg
new file mode 100644
index 0000000..c5b2c36
--- /dev/null
+++ b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/playing.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/sound.svg b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/sound.svg
new file mode 100644
index 0000000..5cb4144
--- /dev/null
+++ b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/imgs/sound.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js
index 0a148d3..04b1193 100644
--- a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js
+++ b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js
@@ -125,6 +125,7 @@ Component({
frameSize: 50,
},
voiceRecognizing: false,
+ speedList: [2, 1.5, 1.25, 1, 0.75],
},
attached: async function () {
const chatMode = this.data.chatMode;
@@ -1912,15 +1913,20 @@ Component({
if (audioContext.recordId === botRecordId) {
// 是则直接播放
audioContext.playStatus = 2;
+ audioContext.showSpeedList = false;
+ // audioContext.currentSpeed = 1.25;
this.setData({
audioContext: audioContext,
});
+ audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
} else {
// 需销毁当前的 audioContext TODO:, 先测试复用content, 直接更换src
audioContext.context.stop(); // 旧的停止
audioContext.recordId = botRecordId;
audioContext.playStatus = 1;
+ audioContext.showSpeedList = false;
+ audioContext.currentSpeed = 1.25;
this.setData({
audioContext: {
...audioContext,
@@ -1930,6 +1936,7 @@ Component({
if (audioUrl) {
audioContext.context.src = audioUrl;
audioContext.context.seek(0); // 播放进度拉回到0
+ audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
this.setData({
audioContext: {
@@ -1952,11 +1959,20 @@ Component({
const audioContext = {
recordId: botRecordId,
playStatus: 1,
+ showSpeedList: false,
+ currentSpeed: 1.25,
};
- const innerAudioContent = wx.createInnerAudioContext({
+ const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false, // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
});
- innerAudioContent.onEnded(() => {
+ try {
+ await wx.setInnerAudioOption({
+ obeyMuteSwitch: false, // 是否遵循系统静音开关,默认遵循
+ });
+ } catch (e) {
+ console.log("不遵循静音模式控制", e);
+ }
+ innerAudioContext.onEnded(() => {
// 音频自然播放至结束触发
this.setData({
audioContext: {
@@ -1965,13 +1981,14 @@ Component({
},
});
});
- audioContext.context = innerAudioContent;
+ audioContext.context = innerAudioContext;
this.setData({
audioContext: audioContext,
});
const audioUrl = await this.fetchAudioUrlByContent(botRecordId, content);
if (audioUrl) {
audioContext.context.src = audioUrl;
+ audioContext.context.playbackRate = audioContext.currentSpeed; // 播放速率,范围 0.5~2.0,默认 1.0
audioContext.context.play();
this.setData({
audioContext: {
@@ -2006,14 +2023,38 @@ Component({
console.log("暂停异常");
}
},
+ toggleSpeedList(e) {
+ this.setData({
+ audioContext: {
+ ...this.data.audioContext,
+ showSpeedList: !this.data.audioContext.showSpeedList,
+ },
+ });
+ },
+ chooseSpeed(e) {
+ const speed = e.currentTarget.dataset.speed;
+ console.log("choose speed", speed);
+ const audioContext = this.data.audioContext;
+ audioContext.showSpeedList = !this.data.audioContext.showSpeedList;
+ audioContext.currentSpeed = Number(speed);
+ audioContext.context.pause();
+ audioContext.context.playbackRate = audioContext.currentSpeed;
+ audioContext.context.play();
+ this.setData({
+ audioContext: {
+ ...this.data.audioContext,
+ ...audioContext,
+ },
+ });
+ },
// 触摸开始
handleTouchStart(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchstart e", e);
const { clientY } = e.touches[0];
@@ -2033,12 +2074,12 @@ Component({
},
// 触摸移动
handleTouchMove(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchMove");
if (!this.data.longPressTriggered) return;
@@ -2061,12 +2102,12 @@ Component({
},
// 触摸结束
handleTouchEnd(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchEnd e", e);
clearTimeout(this.data.longPressTimer);
diff --git a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxml b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxml
index 34298cf..a92187f 100644
--- a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxml
+++ b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxml
@@ -148,18 +148,33 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {{audioContext.currentSpeed || '1'}}X
+
+
+
+
diff --git a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxss b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxss
index b003d93..9549f10 100644
--- a/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxss
+++ b/apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.wxss
@@ -104,9 +104,9 @@
.share_btn {
background-color: #fff;
margin: 0px !important;
- padding: 0px !important;
- width: 36rpx !important;
- height: 36rpx;
+ padding: 0rpx !important;
+ width: 64rpx !important;
+ height: 64rpx;
}
.avatar {
@@ -671,4 +671,65 @@
background-color: rgb(249, 251, 255);
filter: brightness(95%);
transition: filter 0.4s;
+}
+
+.tool_btn {
+ width: 36rpx;
+ height: 36rpx;
+ padding: 10rpx;
+ border: 1rpx solid #cfcdcd;
+ border-radius: 14rpx;
+ /* box-sizing: content-box; */
+}
+
+.playing_btn {
+ height: 36rpx;
+ padding: 10rpx;
+ border: 1rpx solid #cfcdcd;
+ border-radius: 14rpx;
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ position: relative;
+}
+
+.speed-switch {
+ display: flex;
+ align-items: center;
+ margin-left: 0rpx;
+ padding: 4rpx 12rpx;
+ border-radius: 20rpx;
+ /* background: #f5f5f7; */
+ font-size: 26rpx;
+ color: #222;
+ cursor: pointer;
+}
+
+.speed-label {
+ margin-left: 6rpx;
+}
+
+.speed-popup {
+ position: absolute;
+ bottom: 48rpx;
+ right: 0;
+ background: #fff;
+ border-radius: 12rpx;
+ box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
+ z-index: 99;
+ padding: 8rpx 0;
+ min-width: 80rpx;
+}
+
+.speed-option {
+ padding: 16rpx 32rpx;
+ font-size: 28rpx;
+ color: #222;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+}
+
+.speed-option:active {
+ background: #f0f0f0;
}
\ No newline at end of file
diff --git a/components/agent-ui/imgs/playing.svg b/components/agent-ui/imgs/playing.svg
new file mode 100644
index 0000000..c5b2c36
--- /dev/null
+++ b/components/agent-ui/imgs/playing.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/components/agent-ui/imgs/sound.svg b/components/agent-ui/imgs/sound.svg
new file mode 100644
index 0000000..5cb4144
--- /dev/null
+++ b/components/agent-ui/imgs/sound.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/components/agent-ui/index.js b/components/agent-ui/index.js
index 0a148d3..04b1193 100644
--- a/components/agent-ui/index.js
+++ b/components/agent-ui/index.js
@@ -125,6 +125,7 @@ Component({
frameSize: 50,
},
voiceRecognizing: false,
+ speedList: [2, 1.5, 1.25, 1, 0.75],
},
attached: async function () {
const chatMode = this.data.chatMode;
@@ -1912,15 +1913,20 @@ Component({
if (audioContext.recordId === botRecordId) {
// 是则直接播放
audioContext.playStatus = 2;
+ audioContext.showSpeedList = false;
+ // audioContext.currentSpeed = 1.25;
this.setData({
audioContext: audioContext,
});
+ audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
} else {
// 需销毁当前的 audioContext TODO:, 先测试复用content, 直接更换src
audioContext.context.stop(); // 旧的停止
audioContext.recordId = botRecordId;
audioContext.playStatus = 1;
+ audioContext.showSpeedList = false;
+ audioContext.currentSpeed = 1.25;
this.setData({
audioContext: {
...audioContext,
@@ -1930,6 +1936,7 @@ Component({
if (audioUrl) {
audioContext.context.src = audioUrl;
audioContext.context.seek(0); // 播放进度拉回到0
+ audioContext.context.playbackRate = audioContext.currentSpeed;
audioContext.context.play();
this.setData({
audioContext: {
@@ -1952,11 +1959,20 @@ Component({
const audioContext = {
recordId: botRecordId,
playStatus: 1,
+ showSpeedList: false,
+ currentSpeed: 1.25,
};
- const innerAudioContent = wx.createInnerAudioContext({
+ const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false, // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
});
- innerAudioContent.onEnded(() => {
+ try {
+ await wx.setInnerAudioOption({
+ obeyMuteSwitch: false, // 是否遵循系统静音开关,默认遵循
+ });
+ } catch (e) {
+ console.log("不遵循静音模式控制", e);
+ }
+ innerAudioContext.onEnded(() => {
// 音频自然播放至结束触发
this.setData({
audioContext: {
@@ -1965,13 +1981,14 @@ Component({
},
});
});
- audioContext.context = innerAudioContent;
+ audioContext.context = innerAudioContext;
this.setData({
audioContext: audioContext,
});
const audioUrl = await this.fetchAudioUrlByContent(botRecordId, content);
if (audioUrl) {
audioContext.context.src = audioUrl;
+ audioContext.context.playbackRate = audioContext.currentSpeed; // 播放速率,范围 0.5~2.0,默认 1.0
audioContext.context.play();
this.setData({
audioContext: {
@@ -2006,14 +2023,38 @@ Component({
console.log("暂停异常");
}
},
+ toggleSpeedList(e) {
+ this.setData({
+ audioContext: {
+ ...this.data.audioContext,
+ showSpeedList: !this.data.audioContext.showSpeedList,
+ },
+ });
+ },
+ chooseSpeed(e) {
+ const speed = e.currentTarget.dataset.speed;
+ console.log("choose speed", speed);
+ const audioContext = this.data.audioContext;
+ audioContext.showSpeedList = !this.data.audioContext.showSpeedList;
+ audioContext.currentSpeed = Number(speed);
+ audioContext.context.pause();
+ audioContext.context.playbackRate = audioContext.currentSpeed;
+ audioContext.context.play();
+ this.setData({
+ audioContext: {
+ ...this.data.audioContext,
+ ...audioContext,
+ },
+ });
+ },
// 触摸开始
handleTouchStart(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchstart e", e);
const { clientY } = e.touches[0];
@@ -2033,12 +2074,12 @@ Component({
},
// 触摸移动
handleTouchMove(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchMove");
if (!this.data.longPressTriggered) return;
@@ -2061,12 +2102,12 @@ Component({
},
// 触摸结束
handleTouchEnd(e) {
- if(this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
+ if (this.data.chatStatus !== 0 || this.data.voiceRecognizing === true) {
wx.showToast({
title: "请等待对话完成",
icon: "error",
});
- return
+ return;
}
console.log("touchEnd e", e);
clearTimeout(this.data.longPressTimer);
diff --git a/components/agent-ui/index.wxml b/components/agent-ui/index.wxml
index 34298cf..a92187f 100644
--- a/components/agent-ui/index.wxml
+++ b/components/agent-ui/index.wxml
@@ -148,18 +148,33 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {{audioContext.currentSpeed || '1'}}X
+
+
+
+
diff --git a/components/agent-ui/index.wxss b/components/agent-ui/index.wxss
index b003d93..9549f10 100644
--- a/components/agent-ui/index.wxss
+++ b/components/agent-ui/index.wxss
@@ -104,9 +104,9 @@
.share_btn {
background-color: #fff;
margin: 0px !important;
- padding: 0px !important;
- width: 36rpx !important;
- height: 36rpx;
+ padding: 0rpx !important;
+ width: 64rpx !important;
+ height: 64rpx;
}
.avatar {
@@ -671,4 +671,65 @@
background-color: rgb(249, 251, 255);
filter: brightness(95%);
transition: filter 0.4s;
+}
+
+.tool_btn {
+ width: 36rpx;
+ height: 36rpx;
+ padding: 10rpx;
+ border: 1rpx solid #cfcdcd;
+ border-radius: 14rpx;
+ /* box-sizing: content-box; */
+}
+
+.playing_btn {
+ height: 36rpx;
+ padding: 10rpx;
+ border: 1rpx solid #cfcdcd;
+ border-radius: 14rpx;
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ position: relative;
+}
+
+.speed-switch {
+ display: flex;
+ align-items: center;
+ margin-left: 0rpx;
+ padding: 4rpx 12rpx;
+ border-radius: 20rpx;
+ /* background: #f5f5f7; */
+ font-size: 26rpx;
+ color: #222;
+ cursor: pointer;
+}
+
+.speed-label {
+ margin-left: 6rpx;
+}
+
+.speed-popup {
+ position: absolute;
+ bottom: 48rpx;
+ right: 0;
+ background: #fff;
+ border-radius: 12rpx;
+ box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
+ z-index: 99;
+ padding: 8rpx 0;
+ min-width: 80rpx;
+}
+
+.speed-option {
+ padding: 16rpx 32rpx;
+ font-size: 28rpx;
+ color: #222;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+}
+
+.speed-option:active {
+ background: #f0f0f0;
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index f26db3d..28f59c6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cloudbase-agent-ui",
- "version": "1.11.0",
+ "version": "1.12.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cloudbase-agent-ui",
- "version": "1.11.0",
+ "version": "1.12.0",
"license": "MIT",
"dependencies": {
"standard-version": "^9.5.0"
diff --git a/package.json b/package.json
index 0853b9e..6b12845 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cloudbase-agent-ui",
- "version": "1.11.0",
+ "version": "1.12.0",
"description": "微信小程序 Agent UI组件",
"main": "index.js",
"directories": {