EDGE-TTS 0.7.2 更新NodeRed流程配置
项目地址:https://github.com/hasscc/hass-edge-tts
EDGE-TTS是我主要使用的TTS工具,NodeRed中之前写了一个流程模板, 把多个触发自定义TTS事件整合到同一个NodeRed执行流程中
最近随着Home Assistant内核更新, 顺手更新了EDGE-TTS v0.7.2版本,发现当前调用方法发生了调整,那么我之前写的NodeRed模板就用不了了
那么今天我来更新一下我的NodeRed流.
之前使用的模板是用到了function节点+空action节点来实现动态效果:
#function节点关键信息:
msg.payload = {
action: "tts.edge_tts_say",
data: {
entity_id: "media_player.keting_homepod",
message: msg.ttsText,
language: "zh-CN",
options: {
voice: "zh-CN-XiaoxiaoNeural"
}
}
};

此版本(0.7.2)由于调整了platform 为engine_id ,增加了UI配置,hass-edge-tts 的配置和调用方式发生了变化
所以在我的流程中,function节点和action节点都需要进行修改. 特别action节点不能使用空节点了,最新调整流程如下:
#function节点主要修改:
msg.data = {
cache: true,
message: msg.ttsText,
media_player_entity_id: "media_player.shufang_homepod",
language: "zh-CN",
options: {
voice: "zh-CN-XiaoxiaoNeural"
}
};
#action节点用json格式分享
完整的调用配置(直接复制导入NodeRed):
[
{
"id": "4e49a9d7566fd23f",
"type": "group",
"z": "fc340d7dd302465e",
"style": {
"stroke": "#999999",
"stroke-opacity": "1",
"fill": "none",
"fill-opacity": "1",
"label": true,
"label-position": "nw",
"color": "#a4a4a4"
},
"nodes": [
"738b69b21d6f933e",
"7e419f6194dd9607",
"9918cfe4d7f9b8a1",
"2b91a1a02cf27779",
"6389f4ef8ce0e6b8",
"20d2d97793494bd2",
"2e65dfce757391f0",
"40b0dc425e9d87fc",
"b4fac9397dc2089c",
"d89254ade7a02f75",
"6b5aec201e5d4fe2",
"95a6f8a22b54a381",
"74b263274084962c",
"36373cbe13a9fb2e",
"5ae1ebddd765f3c2",
"4edfe6af8d7dd19c",
"f64e32e1194f0006"
],
"x": 1614,
"y": 459,
"w": 1392,
"h": 302
},
{
"id": "738b69b21d6f933e",
"type": "api-current-state",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "HomePod 状态",
"server": "6d42cb4e16b94937",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "media_player.shufang_homepod",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "entity"
},
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "",
"forType": "num",
"x": 1720,
"y": 500,
"wires": [
[
"7e419f6194dd9607"
]
]
},
{
"id": "7e419f6194dd9607",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "播报准备/暂停播放/记录音量",
"func": "msg.original_volume = msg.data.attributes.volume_level || 0.5;\nmsg.was_playing = (msg.data.state === 'playing');\n\nif (msg.was_playing) {\n msg.payload = {\n action: 'media_player.media_pause',\n data: {\n entity_id: 'media_player.shufang_homepod'\n }\n };\n return [msg, null];\n} else {\n return [null, msg];\n}",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1800,
"y": 560,
"wires": [
[
"6b5aec201e5d4fe2"
],
[
"36373cbe13a9fb2e"
]
]
},
{
"id": "9918cfe4d7f9b8a1",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "恢复播前状态",
"func": "if (msg.was_playing) {\n msg.payload = {\n action: 'media_player.media_play',\n data: {\n entity_id: 'media_player.shufang_homepod'\n }\n };\n return msg;\n} else {\n return null;\n}",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2100,
"y": 720,
"wires": [
[
"2b91a1a02cf27779"
]
]
},
{
"id": "2b91a1a02cf27779",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "执行操作",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [],
"labelId": [],
"data": "",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "media_player",
"service": "media_play",
"mergecontext": "",
"x": 2320,
"y": 720,
"wires": [
[
"5ae1ebddd765f3c2"
]
]
},
{
"id": "6389f4ef8ce0e6b8",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "配置TTS文本(edge_tts)",
"func": "// let currentTime = msg.data?.state || '00:00:00';\n// let [hour, minute, second] = currentTime.split(':');\nlet state = msg.payload.routeA;\nlet currentTime = msg.payload.routeB || \"00:00:00\";\nlet [hour, minute] = currentTime.split(':');\n\nlet cleanText = (msg.ttsText || \"测试\")\n .replace(/\\u200B/g, '') // 移除零宽空格\n .replace(/\\uFEFF/g, '') // 移除 BOM\n .trim();\n\n\nmsg.data = {\n cache: true,\n message: msg.ttsText,\n media_player_entity_id: \"media_player.shufang_homepod\",\n language: \"zh-CN\",\n options: {\n voice: \"zh-CN-XiaoxiaoNeural\"\n }\n};\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2350,
"y": 640,
"wires": [
[
"74b263274084962c"
]
]
},
{
"id": "20d2d97793494bd2",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "判断时间段[音量控制]",
"func": "var currentTime = msg.payload; // 获取时间字符串,例如 \"20:51:16\"\nvar timeParts = currentTime.split(':'); // 将时间字符串分割为小时、分钟和秒\nvar hours = parseInt(timeParts[0], 10); // 获取小时部分并转为整数\n\n// 设置默认音量(例如夜间)\nvar broad_volume = 0.2;\n\n// 判断是否在白天(08:00 到 21:00)\nif (hours >= 8 && hours < 21) {\n broad_volume = 0.6;\n}\n\n// 设置音量值到 msg 对象中供后续使用\nmsg.volume_level_set = broad_volume;\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2460,
"y": 560,
"wires": [
[
"40b0dc425e9d87fc"
]
]
},
{
"id": "2e65dfce757391f0",
"type": "api-current-state",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "判断时间段",
"server": "6d42cb4e16b94937",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"entity_id": "sensor.time",
"state_type": "str",
"blockInputOverrides": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "data",
"propertyType": "msg",
"value": "",
"valueType": "entity"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 2250,
"y": 560,
"wires": [
[
"20d2d97793494bd2"
]
]
},
{
"id": "40b0dc425e9d87fc",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "设定通知广播音量",
"func": "msg.payload = {\n action: 'media_player.volume_set',\n data: {\n entity_id: 'media_player.shufang_homepod',\n volume_level: msg.volume_level_set\n }\n};\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2670,
"y": 560,
"wires": [
[
"b4fac9397dc2089c"
]
]
},
{
"id": "b4fac9397dc2089c",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "执行操作",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [],
"labelId": [],
"data": "",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"blockInputOverrides": false,
"domain": "media_player",
"service": "volume_set",
"x": 1920,
"y": 640,
"wires": [
[
"f64e32e1194f0006"
]
]
},
{
"id": "d89254ade7a02f75",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "恢复原音量",
"func": "msg.payload = {\n action: 'media_player.volume_set',\n data: {\n entity_id: 'media_player.shufang_homepod',\n volume_level: msg.original_volume || 0.5\n }\n};\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2750,
"y": 640,
"wires": [
[
"95a6f8a22b54a381"
]
]
},
{
"id": "6b5aec201e5d4fe2",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "执行",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [],
"labelId": [],
"data": "",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"blockInputOverrides": false,
"domain": "media_player",
"service": "media_pause",
"x": 1990,
"y": 500,
"wires": [
[
"36373cbe13a9fb2e"
]
]
},
{
"id": "95a6f8a22b54a381",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "执行操作",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [],
"labelId": [],
"data": "",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "media_player",
"service": "volume_set",
"x": 2920,
"y": 640,
"wires": [
[
"9918cfe4d7f9b8a1"
]
]
},
{
"id": "74b263274084962c",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "执行TTS播报",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "tts.speak",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"tts.edge_tts_2"
],
"labelId": [],
"data": "data",
"dataType": "jsonata",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "all",
"blockInputOverrides": false,
"domain": "tts",
"service": "speak",
"mergecontext": "",
"x": 2570,
"y": 640,
"wires": [
[
"d89254ade7a02f75"
]
]
},
{
"id": "36373cbe13a9fb2e",
"type": "delay",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "",
"pauseType": "delay",
"timeout": "0.5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 2080,
"y": 560,
"wires": [
[
"2e65dfce757391f0"
]
]
},
{
"id": "5ae1ebddd765f3c2",
"type": "function",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "结束流程,清理变量",
"func": "// 清除重要流程变量\ndelete msg.original_volume;\ndelete msg.was_playing;\ndelete msg.payload;\n\nflow.set(\"tts_context\", undefined);\nglobal.set(\"some_global\", undefined);\n\n\nmsg.cleaned = true; // 添加一个标记\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 2490,
"y": 720,
"wires": [
[]
]
},
{
"id": "4edfe6af8d7dd19c",
"type": "comment",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "TTS播报流程[书房]",
"info": "",
"x": 1790,
"y": 720,
"wires": []
},
{
"id": "f64e32e1194f0006",
"type": "api-call-service",
"z": "fc340d7dd302465e",
"g": "4e49a9d7566fd23f",
"name": "播放 test.mp3",
"server": "6d42cb4e16b94937",
"version": 7,
"debugenabled": false,
"action": "media_player.play_media",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"media_player.shufang_homepod"
],
"labelId": [],
"data": "{\"media_content_id\":\"http://10.0.0.90:8123/local/sound/002.mp3\",\"media_content_type\":\"music\"}",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": false,
"domain": "media_player",
"service": "play_media",
"mergecontext": "",
"x": 2120,
"y": 640,
"wires": [
[
"6389f4ef8ce0e6b8"
]
]
},
{
"id": "6d42cb4e16b94937",
"type": "server",
"name": "Home Assistant_main",
"version": 5,
"addon": true,
"rejectUnauthorizedCerts": true,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": true,
"cacheJson": true,
"heartbeat": true,
"heartbeatInterval": 30,
"areaSelector": "friendlyName",
"deviceSelector": "friendlyName",
"entitySelector": "friendlyName",
"statusSeparator": ": ",
"statusYear": "hidden",
"statusMonth": "short",
"statusDay": "numeric",
"statusHourCycle": "default",
"statusTimeFormat": "h:m",
"enableGlobalContextStore": true
}
]