通过萤石语音上传和下发接口,实现语音内容到设备的广播播放。
在使用此技能前,请完成以下安全检查:
#检查项状态说明1凭证权限⚠️ 必需使用 最小权限 的 AppKey/AppSecret,不要用主账号凭证2配置文件读取⚠️ 注意技能会读取 ~/.openclaw/*.json 文件( 但环境变量优先级更高)3Token 缓存⚠️ 注意Token 缓存在 /tmp/ezviz_global_token_cache/ (权限 600)4系统命令⚠️ 注意使用 say/ espeak/ ffmpeg 进行 TTS (通过 subprocess)5API 域名✅ 已验证openai.ys7.com 是萤石官方 API 端点( openai = Open API,不是 AI)6代码审查✅ 推荐审查 scripts/audio_broadcast.py 和 lib/token_manager.py
凭证获取优先级(从高到低):
text
┌─────────────────────────────────────────────────────────────┐
│ 1. 环境变量 (最高优先级 - 推荐) │
│ ├─ EZVIZ_APP_KEY │
│ ├─ EZVIZ_APP_SECRET │
│ └─ EZVIZ_DEVICE_SERIAL │
│ ✅ 优点:不读取配置文件,完全隔离 │
├─────────────────────────────────────────────────────────────┤
│ 2. OpenClaw 配置文件 (仅当环境变量未设置时使用) │
│ ├─ ~/.openclaw/config.json │
│ ├─ ~/.openclaw/gateway/config.json │
│ └─ ~/.openclaw/channels.json │
│ ⚠️ 注意:只读取 channels.ezviz 字段,不读取其他服务凭证 │
├─────────────────────────────────────────────────────────────┤
│ 3. 命令行参数 (最低优先级) │
│ python3 audio_broadcast.py appKey appSecret deviceSerial │
└─────────────────────────────────────────────────────────────┘
安全建议:
bash
# 1. 使用环境变量(优先级最高,避免配置文件意外使用)
export EZVIZ_APP_KEY="your_dedicated_app_key"
export EZVIZ_APP_SECRET="your_dedicated_app_secret"
export EZVIZ_DEVICE_SERIAL="device1,device2"
# 2. 高安全环境:禁用 Token 缓存
export EZVIZ_TOKEN_CACHE=0
# 3. 测试凭证(推荐先用测试账号)
# 登录 https://openai.ys7.com/ 创建专用应用,仅开通语音相关权限
技能按以下顺序获取凭证( 优先级从高到低):
EZVIZ_APP_KEY, EZVIZ_APP_SECRET) ← 推荐~/.openclaw/config.json 等)bash
pip install requests
bash
export EZVIZ_APP_KEY="your_app_key"
export EZVIZ_APP_SECRET="your_app_secret"
export EZVIZ_DEVICE_SERIAL="dev1,dev2,dev3"
可选环境变量:
bash
export EZVIZ_CHANNEL_NO="1" # 通道号,默认 1
export EZVIZ_AUDIO_FILE="/path/to/audio.mp3" # 本地音频文件路径(二选一)
export EZVIZ_TEXT_CONTENT="语音内容文本" # 文本内容(二选一)
export EZVIZ_VOICE_NAME="custom_name" # 自定义语音名称
export EZVIZ_TOKEN_CACHE="1" # Token 缓存:1=启用 (默认), 0=禁用
Token 缓存说明:
EZVIZ_TOKEN_CACHE=0 每次重新获取 Token/tmp/ezviz_global_token_cache/global_token_cache.json注意:
EZVIZ_ACCESS_TOKEN!技能会自动获取 TokenEZVIZ_AUDIO_FILE 或 EZVIZ_TEXT_CONTENT 其中一个support_talk=1或3)bash
python3 {baseDir}/scripts/audio_broadcast.py
命令行参数:
bash
# 使用本地音频文件
python3 {baseDir}/scripts/audio_broadcast.py appKey appSecret dev1 /path/to/audio.mp3 [channel_no]
# 使用文本内容(自动生成语音)
python3 {baseDir}/scripts/audio_broadcast.py appKey appSecret dev1 "语音内容文本" [channel_no]
text
1. 获取 Token (appKey + appSecret → accessToken)
↓
2a. 如果提供音频文件:直接上传文件
2b. 如果提供文本:调用TTS生成音频文件,然后上传
↓
3. 下发语音 (accessToken + deviceSerial + fileUrl → 设备播放)
↓
4. 输出结果 (JSON + 控制台)
你不需要手动获取或配置 EZVIZ_ACCESS_TOKEN!
技能会自动处理 Token 的获取:
text
首次运行:
appKey + appSecret → 调用萤石 API → 获取 accessToken (有效期 7 天)
↓
保存到缓存文件(系统临时目录)
↓
后续运行:
检查缓存 Token 是否过期
├─ 未过期 → 直接使用缓存 Token ✅
└─ 已过期 → 重新获取新 Token
Token 管理特性:
EZVIZ_ACCESS_TOKEN 环境变量EZVIZ_TOKEN_CACHE=0 可禁用缓存(每次运行重新获取)text
======================================================================
Ezviz Audio Broadcast Skill (萤石语音广播)
======================================================================
[Time] 2026-03-16 16:30:00
[INFO] Target devices: 2
- dev1 (Channel: 1)
- dev2 (Channel: 1)
[INFO] Mode: Text-to-Speech
[INFO] Content: 接下来插播一个广告
======================================================================
[Step 1] Getting access token...
[SUCCESS] Token obtained, expires: 2026-03-23 16:30:00
======================================================================
[Step 2] Generating and uploading audio...
[INFO] Generated TTS file: /tmp/ezviz_tts_12345.mp3
[SUCCESS] Audio uploaded successfully!
[INFO] Voice Name: ad_broadcast
[INFO] File URL: https://oss-cn-shenzhen.aliyuncs.com/voice/...
======================================================================
[Step 3] Broadcasting audio to devices...
======================================================================
[Device] dev1 (Channel: 1)
[SUCCESS] Audio broadcast completed!
[Device] dev2 (Channel: 1)
[SUCCESS] Audio broadcast completed!
======================================================================
BROADCAST SUMMARY
======================================================================
Total devices: 2
Success: 2
Failed: 0
======================================================================
格式示例说明单设备dev1默认通道 1多设备dev1,dev2,dev3全部使用默认通道指定通道dev1:1,dev2:2每个设备独立通道混合dev1,dev2:2,dev3部分指定通道
接口URL文档获取 TokenPOST /api/lapp/token/gethttps://openai.ys7.com/help/81语音上传POST /api/lapp/voice/uploadhttps://openai.ys7.com/help/1241语音下发POST /api/lapp/voice/sendhttps://openai.ys7.com/help/1253
域名用途openai.ys7.com萤石开放平台 API(Token、语音上传、下发)
格式支持限制WAV✅最大5MB,最长60秒MP3✅最大5MB,最长60秒AAC✅最大5MB,最长60秒
⚠️ 设备兼容性: 设备必须支持对讲功能( support_talk=1或3),否则返回错误码 20015
⚠️ 频率限制: 语音下发接口有调用频率限制,建议设备间间隔1秒以上
⚠️ 文件大小: 音频文件不能超过5MB,时长不能超过60秒
⚠️ Token 安全: Token 缓存到系统临时目录(权限 600),不写入日志,不发送到非萤石端点
⚠️ TTS依赖: 文本转语音功能依赖系统TTS服务,确保系统支持
本技能会向第三方服务发送数据:
数据类型发送到用途是否必需音频文件openai.ys7.com (萤石)语音上传和下发✅ 必需appKey/appSecretopenai.ys7.com (萤石)获取访问 Token✅ 必需设备序列号openai.ys7.com (萤石)请求下发✅ 必需EZVIZ_ACCESS_TOKEN自动生成每次运行自动获取****✅ 自动
数据流出说明:
openai.ys7.com): 所有API调用 - 萤石官方 API凭证权限建议:
本地处理:
场景1: 紧急安全通知
bash
python3 audio_broadcast.py your_key your_secret "kitchen_cam,dining_area" "注意!检测到安全隐患,请立即检查!"
场景2: 商业促销广播
bash
export EZVIZ_TEXT_CONTENT="欢迎光临!今日特价商品限时优惠,详情请咨询店员!"
export EZVIZ_DEVICE_SERIAL="store_front,store_back"
python3 audio_broadcast.py
场景3: 使用预录制音频
bash
python3 audio_broadcast.py your_key your_secret entrance_cam /path/to/welcome_message.mp3
接口URL文档获取 TokenPOST /api/lapp/token/gethttps://open.ys7.com/help/81语音上传POST /api/lapp/voice/uploadhttps://open.ys7.com/help/1241语音下发POST /api/lapp/voice/sendhttps://open.ys7.com/help/1253
API 域名: https://openai.ys7.com (萤石开放平台 API 专用)
为什么是 openai.ys7.com 而不是 open.ys7.com?
域名用途说明openai.ys7.com✅ API 接口萤石开放平台 API 专用域名(AI 不是指人工智能)open.ys7.com🌐 官方网站萤石开放平台 官网/文档 入口
openai 的含义: 这里是 "Open API" 的缩写, 不是 指 OpenAI 或人工智能。
bash
# 验证 API 域名连通性
curl -I https://openai.ys7.com/api/lapp/token/get
# 验证官网连通性
curl -I https://open.ys7.com/
# 检查 SSL 证书(API 域名)
curl -vI https://openai.ys7.com/api/lapp/token/get 2>&1 | grep -A5 "SSL certificate"
# 验证域名所有权(萤石)
whois ys7.com
官方文档: https://open.ys7.com/
安全提示:
openai.ys7.com 是萤石官方 API 域名技能会读取以下路径中的萤石配置(仅当环境变量未设置时):
text
~/.openclaw/config.json
~/.openclaw/gateway/config.json
~/.openclaw/channels.json
配置格式:
json
{
"channels": {
"ezviz": {
"appId": "your_app_id",
"appSecret": "your_app_secret",
"domain": "https://openai.ys7.com",
"enabled": true
}
}
}
安全建议:
禁用配置文件扫描(环境变量优先):
bash
export EZVIZ_APP_KEY="your_key"
export EZVIZ_APP_SECRET="your_secret"
# 环境变量优先级高于配置文件
Python 包:
bash
pip install requests
系统工具 (仅 TTS 需要):
say, afconvertespeak, ffmpeg技能通过 subprocess 调用系统 TTS 命令:
python
# macOS TTS
subprocess.run(['say', '-o', temp_aiff, text_with_pauses], check=True, capture_output=True)
subprocess.run(['afconvert', '-f', 'WAVE', '-d', 'LEI16@44100', temp_aiff, output_path], ...)
# Linux TTS
subprocess.run(['espeak', '-w', output_path, text], check=True, capture_output=True)
subprocess.run(['ffmpeg', '-i', input, '-acodec', 'libmp3lame', output], ...)
安全措施 (v1.0.2+):
validate_text_input() 验证;, |, &, $(), 等字符的输入输入验证规则:
检查项限制说明空内容❌ 拒绝文本不能为空长度≤500 字符防止过长输入危险字符❌ 拒绝;, `设备序列号字母数字只允许 A-Za-z0-9_:,
安全建议:
text_to_speech() 函数不使用 TTS (仅提供音频文件,避免系统命令):
bash
python3 scripts/audio_broadcast.py appKey appSecret deviceSerial --audio-file /path/to/audio.mp3
必需环境变量 (在 SKILL.md metadata 中声明):
yaml
metadata:
openclaw:
requires:
env: ["EZVIZ_APP_KEY", "EZVIZ_APP_SECRET", "EZVIZ_DEVICE_SERIAL"]
⚠️ 注意: 如果 Registry metadata 未显示必需环境变量,以 SKILL.md 为准。
默认行为:
/tmp/ezviz_global_token_cache/global_token_cache.json)缓存位置查询:
bash
# macOS
ls -la /var/folders/*/T/ezviz_global_token_cache/
# Linux
ls -la /tmp/ezviz_global_token_cache/
# 查看缓存内容(脱敏)
cat /tmp/ezviz_global_token_cache/global_token_cache.json
⚠️ 潜在风险:
风险等级说明Token 明文存储🟡 中文件权限 600,但仍是明文跨技能共享🟡 中同一用户的技能可共享 Token多用户系统🟠 高其他用户可能访问临时目录临时目录清理🟢 低系统重启可能清理临时文件
禁用缓存 (高安全环境/共享系统):
bash
export EZVIZ_TOKEN_CACHE=0
python3 scripts/audio_broadcast.py ...
清除缓存:
bash
# 清除所有缓存 Token
rm -rf /tmp/ezviz_global_token_cache/
# 或使用 Token 管理器
python3 lib/token_manager.py clear
安全建议:
环境建议单用户个人设备✅ 默认缓存安全(文件权限 600)多用户共享系统⚠️ 设置 EZVIZ_TOKEN_CACHE=0高安全环境⚠️ 禁用缓存 + 专用 OS 用户 + 容器隔离生产环境⚠️ 容器/VM 隔离 + 禁用缓存 + 密钥管理器
⚠️ 早期版本用户必须轮换凭证!
如果您曾经使用过旧版本的 .env 文件:
text
🚨 您的凭证可能已泄露!
立即执行:
1. 登录 https://openai.ys7.com/
2. 删除旧应用,创建新应用
3. 获取新的 AppKey 和 AppSecret
正确做法:
数据类型发送到用途AppKey/AppSecretopenai.ys7.com获取 Token设备序列号openai.ys7.comAPI 调用音频文件openai.ys7.com语音上传
推荐审查的文件:
scripts/audio_broadcast.py - 主脚本lib/token_manager.py - Token 管理器代码特点:
requests 库(标准做法)subprocess 带列表参数(减少 shell 注入风险)安装前:
安装时:
EZVIZ_TOKEN_CACHE=0(共享系统/多用户环境)安装后:
根据安全审计建议,请在安装前完成以下检查:
scripts/audio_broadcast.py 和 lib/token_manager.pyopenai.ys7.com 是萤石官方端点~/.openclaw/*.json 中是否有敏感凭证/tmp/ezviz_global_token_cache/ 可接受EZVIZ_APP_KEY 等环境变量EZVIZ_TOKEN_CACHE=0requests 等依赖的安全更新更新日志:
日期版本变更说明2026-03-181.0.5完整披露 metadata添加 configFileRead 和 tokenCache 完整说明2026-03-181.0.5明确优先级环境变量 > 配置文件 > 命令行参数2026-03-181.0.4澄清 API 域名说明 openai.ys7.com 是官方 API 域名( openai = Open API)2026-03-181.0.3修复 metadata添加 config.tokenCache 配置说明2026-03-181.0.3明确缓存行为默认启用缓存,支持 EZVIZ_TOKEN_CACHE=0 禁用2026-03-181.0.2添加输入验证validate_text_input() 和 validate_device_serial()2026-03-181.0.2添加凭证来源警告从配置文件读取时显示警告2026-03-181.0.2更新 metadata 格式使用 YAML 格式,添加 warnings 字段2026-03-181.0.1修复 Token 缓存 buguse_cache=None 改为 use_cache=True2026-03-181.0.1添加安全审计清单根据安全建议添加完整检查清单2026-03-181.0.1明确配置文件行为说明 ~/.openclaw/*.json 读取逻辑2026-03-181.0.1添加 API 域名验证提供域名和 SSL 验证命令2026-03-181.0.1添加 TTS 安全说明说明 subprocess 调用系统命令的安全措施
最后更新: 2026-03-18
版本: 1.0.5 (完整信息披露版)
技能支持从 OpenClaw 的 channels 配置中自动读取萤石凭证,无需单独设置环境变量。
在 ~/.openclaw/config.json 或 ~/.openclaw/channels.json 中添加:
json
{
"channels": {
"ezviz": {
"appId": "your_app_id",
"appSecret": "your_app_secret",
"domain": "https://openai.ys7.com",
"enabled": true
}
}
}
技能会按以下顺序查找配置文件:
~/.openclaw/config.json~/.openclaw/gateway/config.json~/.openclaw/channels.json凭证获取优先级:
环境变量 (最高优先级)
EZVIZ_APP_KEYEZVIZ_APP_SECRETChannels 配置 (中等优先级)
channels.ezviz.appIdchannels.ezviz.appSecret命令行参数 (最低优先级)