n8n-nodes-speechsense 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/credentials/SpeechSenseApi.credentials.js +29 -0
- package/dist/nodes/SpeechSense/GenericFunctions.js +85 -0
- package/dist/nodes/SpeechSense/SpeechSense.node.js +178 -0
- package/dist/nodes/SpeechSense/talk_service.proto +84 -0
- package/index.js +3 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 x0cfwm
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# n8n-nodes-speechsense
|
|
2
|
+
|
|
3
|
+
An [n8n](https://n8n.io) community node that uploads talks (call recordings) to
|
|
4
|
+
**Yandex SpeechSense** (Talk Analytics).
|
|
5
|
+
|
|
6
|
+
SpeechSense exposes talk **upload only over gRPC** (`api.speechsense.yandexcloud.net:443`)
|
|
7
|
+
— the REST host serves read methods (search/get) only. This node speaks that gRPC
|
|
8
|
+
API directly using a bundled, self-contained subset of the official protobuf, so no
|
|
9
|
+
code generation or external proto files are required at runtime.
|
|
10
|
+
|
|
11
|
+
## Operations
|
|
12
|
+
|
|
13
|
+
- **Talk → Upload Audio** — `TalkService.Upload`. Sends one audio recording (MP3 / WAV /
|
|
14
|
+
OGG-Opus) plus talk metadata and per-user metadata to a SpeechSense connection.
|
|
15
|
+
|
|
16
|
+
## Credentials
|
|
17
|
+
|
|
18
|
+
**SpeechSense API**
|
|
19
|
+
- **API Key** — a Yandex Cloud service-account API key with the SpeechSense upload role.
|
|
20
|
+
Paste the raw key; the node adds the `Api-Key ` prefix.
|
|
21
|
+
- **gRPC Endpoint** — defaults to `api.speechsense.yandexcloud.net:443`.
|
|
22
|
+
|
|
23
|
+
## Node parameters
|
|
24
|
+
|
|
25
|
+
| Field | Notes |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| Connection ID | Target SpeechSense connection. |
|
|
28
|
+
| Input Binary Field | Item binary property holding the audio file (default `data`). |
|
|
29
|
+
| Audio Type | `MP3` / `WAV` / `OGG/Opus`. |
|
|
30
|
+
| Talk ID | Optional; leave blank to create a new talk. |
|
|
31
|
+
| Metadata Fields (JSON) | `{ "key": "value" }` map of connection-defined fields. |
|
|
32
|
+
| Users (JSON) | `[{ "id", "role": "USER_ROLE_OPERATOR"\|"USER_ROLE_CLIENT", "fields": {} }]`. |
|
|
33
|
+
|
|
34
|
+
The node returns `{ talk_id }` for each uploaded item.
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpeechSenseApi = void 0;
|
|
4
|
+
class SpeechSenseApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'speechSenseApi';
|
|
7
|
+
this.displayName = 'SpeechSense API';
|
|
8
|
+
this.documentationUrl = 'https://yandex.cloud/docs/speechsense/';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
name: 'apiKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
typeOptions: { password: true },
|
|
15
|
+
default: '',
|
|
16
|
+
required: true,
|
|
17
|
+
description: 'Yandex Cloud service-account API key with the SpeechSense upload role. Paste the raw key only — the node adds the "Api-Key " prefix itself.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'gRPC Endpoint',
|
|
21
|
+
name: 'endpoint',
|
|
22
|
+
type: 'string',
|
|
23
|
+
default: 'api.speechsense.yandexcloud.net:443',
|
|
24
|
+
description: 'SpeechSense gRPC data-plane endpoint as host:port.',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.SpeechSenseApi = SpeechSenseApi;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.uploadTalk = uploadTalk;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const grpc = __importStar(require("@grpc/grpc-js"));
|
|
39
|
+
const protoLoader = __importStar(require("@grpc/proto-loader"));
|
|
40
|
+
// The generated gRPC client constructor, cached across executions.
|
|
41
|
+
let cachedServiceCtor;
|
|
42
|
+
function getTalkServiceCtor() {
|
|
43
|
+
if (cachedServiceCtor)
|
|
44
|
+
return cachedServiceCtor;
|
|
45
|
+
const protoPath = path.join(__dirname, 'talk_service.proto');
|
|
46
|
+
const definition = protoLoader.loadSync(protoPath, {
|
|
47
|
+
keepCase: true,
|
|
48
|
+
longs: String,
|
|
49
|
+
enums: String,
|
|
50
|
+
defaults: true,
|
|
51
|
+
oneofs: true,
|
|
52
|
+
});
|
|
53
|
+
const pkg = grpc.loadPackageDefinition(definition);
|
|
54
|
+
cachedServiceCtor = pkg.yandex.cloud.speechsense.v1.TalkService;
|
|
55
|
+
return cachedServiceCtor;
|
|
56
|
+
}
|
|
57
|
+
/** Call TalkService.Upload (unary, TLS, Api-Key auth) and resolve the response. */
|
|
58
|
+
async function uploadTalk(creds, request, timeoutMs = 120000) {
|
|
59
|
+
const Ctor = getTalkServiceCtor();
|
|
60
|
+
const endpoint = (creds.endpoint || 'api.speechsense.yandexcloud.net:443').trim();
|
|
61
|
+
const channelCreds = grpc.credentials.createSsl();
|
|
62
|
+
const client = new Ctor(endpoint, channelCreds, {
|
|
63
|
+
'grpc.max_send_message_length': 128 * 1024 * 1024,
|
|
64
|
+
'grpc.max_receive_message_length': 16 * 1024 * 1024,
|
|
65
|
+
});
|
|
66
|
+
const metadata = new grpc.Metadata();
|
|
67
|
+
metadata.add('authorization', `Api-Key ${creds.apiKey}`);
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const deadline = new Date(Date.now() + timeoutMs);
|
|
70
|
+
client.Upload(request, metadata, { deadline }, (err, response) => {
|
|
71
|
+
try {
|
|
72
|
+
client.close();
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* noop */
|
|
76
|
+
}
|
|
77
|
+
if (err) {
|
|
78
|
+
const code = err.code !== undefined ? err.code : '?';
|
|
79
|
+
reject(new Error(`SpeechSense Upload failed [gRPC ${code}]: ${err.details || err.message}`));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
resolve(response);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpeechSense = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const GenericFunctions_1 = require("./GenericFunctions");
|
|
6
|
+
/** Coerce an arbitrary value into a flat { string: string } map. */
|
|
7
|
+
function asStringMap(value) {
|
|
8
|
+
const out = {};
|
|
9
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
10
|
+
for (const [k, v] of Object.entries(value)) {
|
|
11
|
+
if (v === undefined || v === null)
|
|
12
|
+
continue;
|
|
13
|
+
out[k] = typeof v === 'string' ? v : String(v);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function parseMaybeJson(value, fallback) {
|
|
19
|
+
if (typeof value !== 'string')
|
|
20
|
+
return value ?? fallback;
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
return fallback;
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(trimmed);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return fallback;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class SpeechSense {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.description = {
|
|
34
|
+
displayName: 'SpeechSense',
|
|
35
|
+
name: 'speechSense',
|
|
36
|
+
icon: 'fa:cloud-upload-alt',
|
|
37
|
+
group: ['output'],
|
|
38
|
+
version: 1,
|
|
39
|
+
subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
|
|
40
|
+
description: 'Загрузка диалогов в Yandex SpeechSense (Talk Analytics) по gRPC',
|
|
41
|
+
defaults: { name: 'SpeechSense' },
|
|
42
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
43
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
44
|
+
credentials: [{ name: 'speechSenseApi', required: true }],
|
|
45
|
+
properties: [
|
|
46
|
+
{
|
|
47
|
+
displayName: 'Resource',
|
|
48
|
+
name: 'resource',
|
|
49
|
+
type: 'options',
|
|
50
|
+
noDataExpression: true,
|
|
51
|
+
default: 'talk',
|
|
52
|
+
options: [{ name: 'Talk', value: 'talk' }],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Operation',
|
|
56
|
+
name: 'operation',
|
|
57
|
+
type: 'options',
|
|
58
|
+
noDataExpression: true,
|
|
59
|
+
default: 'uploadAudio',
|
|
60
|
+
displayOptions: { show: { resource: ['talk'] } },
|
|
61
|
+
options: [
|
|
62
|
+
{
|
|
63
|
+
name: 'Upload Audio',
|
|
64
|
+
value: 'uploadAudio',
|
|
65
|
+
action: 'Upload an audio talk',
|
|
66
|
+
description: 'Залить аудиозапись разговора (TalkService.Upload, gRPC)',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
displayName: 'Connection ID',
|
|
72
|
+
name: 'connectionId',
|
|
73
|
+
type: 'string',
|
|
74
|
+
required: true,
|
|
75
|
+
default: '',
|
|
76
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
77
|
+
description: 'ID коннекции SpeechSense, в которую заливается разговор',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'Input Binary Field',
|
|
81
|
+
name: 'binaryPropertyName',
|
|
82
|
+
type: 'string',
|
|
83
|
+
required: true,
|
|
84
|
+
default: 'data',
|
|
85
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
86
|
+
description: 'Имя входного бинарного поля с аудиофайлом',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
displayName: 'Audio Type',
|
|
90
|
+
name: 'audioType',
|
|
91
|
+
type: 'options',
|
|
92
|
+
default: 'CONTAINER_AUDIO_TYPE_MP3',
|
|
93
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
94
|
+
options: [
|
|
95
|
+
{ name: 'MP3', value: 'CONTAINER_AUDIO_TYPE_MP3' },
|
|
96
|
+
{ name: 'WAV', value: 'CONTAINER_AUDIO_TYPE_WAV' },
|
|
97
|
+
{ name: 'OGG / Opus', value: 'CONTAINER_AUDIO_TYPE_OGG_OPUS' },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
displayName: 'Talk ID',
|
|
102
|
+
name: 'talkId',
|
|
103
|
+
type: 'string',
|
|
104
|
+
default: '',
|
|
105
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
106
|
+
description: 'Необязательно. Пусто — создаётся новый talk; заданный — обновление метаданных.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'Metadata Fields (JSON)',
|
|
110
|
+
name: 'fields',
|
|
111
|
+
type: 'json',
|
|
112
|
+
default: '{}',
|
|
113
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
114
|
+
description: 'Объект строковых полей метаданных диалога (ключи, заданные в коннекции)',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
displayName: 'Users (JSON)',
|
|
118
|
+
name: 'users',
|
|
119
|
+
type: 'json',
|
|
120
|
+
default: '[]',
|
|
121
|
+
displayOptions: { show: { resource: ['talk'], operation: ['uploadAudio'] } },
|
|
122
|
+
description: 'Массив участников: [{ "id": "...", "role": "USER_ROLE_OPERATOR" | "USER_ROLE_CLIENT", "fields": { } }]',
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async execute() {
|
|
128
|
+
const items = this.getInputData();
|
|
129
|
+
const c = (await this.getCredentials('speechSenseApi'));
|
|
130
|
+
const creds = {
|
|
131
|
+
apiKey: c.apiKey,
|
|
132
|
+
endpoint: c.endpoint || 'api.speechsense.yandexcloud.net:443',
|
|
133
|
+
};
|
|
134
|
+
const returnData = [];
|
|
135
|
+
for (let i = 0; i < items.length; i++) {
|
|
136
|
+
try {
|
|
137
|
+
const connectionId = this.getNodeParameter('connectionId', i);
|
|
138
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
139
|
+
const audioType = this.getNodeParameter('audioType', i);
|
|
140
|
+
const talkId = this.getNodeParameter('talkId', i, '');
|
|
141
|
+
const fieldsRaw = parseMaybeJson(this.getNodeParameter('fields', i, {}), {});
|
|
142
|
+
const usersRaw = parseMaybeJson(this.getNodeParameter('users', i, []), []);
|
|
143
|
+
const fields = asStringMap(fieldsRaw);
|
|
144
|
+
const users = Array.isArray(usersRaw)
|
|
145
|
+
? usersRaw.map((u) => ({
|
|
146
|
+
id: String(u.id ?? ''),
|
|
147
|
+
role: String(u.role ?? 'USER_ROLE_UNSPECIFIED'),
|
|
148
|
+
fields: asStringMap(u.fields),
|
|
149
|
+
}))
|
|
150
|
+
: [];
|
|
151
|
+
const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
|
152
|
+
const request = {
|
|
153
|
+
metadata: { connection_id: connectionId, fields, users },
|
|
154
|
+
audio: {
|
|
155
|
+
audio_metadata: { container_audio: { container_audio_type: audioType } },
|
|
156
|
+
audio_data: { data: buffer },
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
if (talkId)
|
|
160
|
+
request.talk_id = talkId;
|
|
161
|
+
const response = await (0, GenericFunctions_1.uploadTalk)(creds, request);
|
|
162
|
+
returnData.push({
|
|
163
|
+
json: { talk_id: response?.talk_id ?? null, connection_id: connectionId },
|
|
164
|
+
pairedItem: { item: i },
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (this.continueOnFail()) {
|
|
169
|
+
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return [returnData];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.SpeechSense = SpeechSense;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package yandex.cloud.speechsense.v1;
|
|
4
|
+
|
|
5
|
+
// Minimal, self-contained subset of the Yandex SpeechSense Talk API, sufficient
|
|
6
|
+
// for TalkService.Upload (single-message audio upload). Message/field/enum
|
|
7
|
+
// numbers match the official protos (yandex-cloud/cloudapi:
|
|
8
|
+
// yandex/cloud/speechsense/v1/{talk_service,audio}.proto) so the binary wire
|
|
9
|
+
// format is compatible. Streaming/text/search RPCs are intentionally omitted.
|
|
10
|
+
|
|
11
|
+
service TalkService {
|
|
12
|
+
// Upload a talk document as a single message.
|
|
13
|
+
rpc Upload(UploadTalkRequest) returns (UploadTalkResponse);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
message UploadTalkRequest {
|
|
17
|
+
TalkMetadata metadata = 1;
|
|
18
|
+
AudioRequest audio = 2;
|
|
19
|
+
// Blank for initial upload; set to update an existing talk's metadata.
|
|
20
|
+
string talk_id = 3;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
message UploadTalkResponse {
|
|
24
|
+
// id of the created talk document
|
|
25
|
+
string talk_id = 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
message TalkMetadata {
|
|
29
|
+
// id of the connection this talk belongs to
|
|
30
|
+
string connection_id = 1;
|
|
31
|
+
// connection-defined metadata fields
|
|
32
|
+
map<string, string> fields = 2;
|
|
33
|
+
// per-user metadata
|
|
34
|
+
repeated UserMetadata users = 3;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
message UserMetadata {
|
|
38
|
+
string id = 1;
|
|
39
|
+
UserRole role = 2;
|
|
40
|
+
map<string, string> fields = 3;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
enum UserRole {
|
|
44
|
+
USER_ROLE_UNSPECIFIED = 0;
|
|
45
|
+
USER_ROLE_OPERATOR = 1;
|
|
46
|
+
USER_ROLE_CLIENT = 2;
|
|
47
|
+
USER_ROLE_BOT = 3;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
message RawAudio {
|
|
51
|
+
enum AudioEncoding {
|
|
52
|
+
AUDIO_ENCODING_UNSPECIFIED = 0;
|
|
53
|
+
AUDIO_ENCODING_LINEAR16_PCM = 1;
|
|
54
|
+
}
|
|
55
|
+
AudioEncoding audio_encoding = 1;
|
|
56
|
+
int64 sample_rate_hertz = 2;
|
|
57
|
+
int64 audio_channel_count = 3;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
message ContainerAudio {
|
|
61
|
+
enum ContainerAudioType {
|
|
62
|
+
CONTAINER_AUDIO_TYPE_UNSPECIFIED = 0;
|
|
63
|
+
CONTAINER_AUDIO_TYPE_WAV = 1;
|
|
64
|
+
CONTAINER_AUDIO_TYPE_OGG_OPUS = 2;
|
|
65
|
+
CONTAINER_AUDIO_TYPE_MP3 = 3;
|
|
66
|
+
}
|
|
67
|
+
ContainerAudioType container_audio_type = 1;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
message AudioMetadata {
|
|
71
|
+
oneof AudioFormat {
|
|
72
|
+
RawAudio raw_audio = 1;
|
|
73
|
+
ContainerAudio container_audio = 2;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
message AudioChunk {
|
|
78
|
+
bytes data = 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
message AudioRequest {
|
|
82
|
+
AudioMetadata audio_metadata = 1;
|
|
83
|
+
AudioChunk audio_data = 2;
|
|
84
|
+
}
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-speechsense",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n community node to upload call/chat talks to Yandex SpeechSense (Talk Analytics) over gRPC",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"speechsense",
|
|
8
|
+
"yandex",
|
|
9
|
+
"talk-analytics",
|
|
10
|
+
"grpc",
|
|
11
|
+
"speech"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "x0cfwm",
|
|
16
|
+
"url": "https://github.com/x0cfwm"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/x0cfwm/n8n-nodes-speechsense.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/x0cfwm/n8n-nodes-speechsense#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/x0cfwm/n8n-nodes-speechsense/issues"
|
|
25
|
+
},
|
|
26
|
+
"main": "index.js",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "rm -rf dist && tsc && npm run copy:assets",
|
|
29
|
+
"prepare": "npm run build",
|
|
30
|
+
"copy:assets": "mkdir -p dist/nodes/SpeechSense && cp nodes/SpeechSense/*.proto dist/nodes/SpeechSense/ 2>/dev/null || true",
|
|
31
|
+
"dev": "tsc --watch",
|
|
32
|
+
"typecheck": "tsc --noEmit"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"index.js"
|
|
37
|
+
],
|
|
38
|
+
"n8n": {
|
|
39
|
+
"n8nNodesApiVersion": 1,
|
|
40
|
+
"credentials": [
|
|
41
|
+
"dist/credentials/SpeechSenseApi.credentials.js"
|
|
42
|
+
],
|
|
43
|
+
"nodes": [
|
|
44
|
+
"dist/nodes/SpeechSense/SpeechSense.node.js"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@grpc/grpc-js": "^1.10.0",
|
|
49
|
+
"@grpc/proto-loader": "^0.7.10"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^20.14.0",
|
|
53
|
+
"n8n-workflow": "*",
|
|
54
|
+
"typescript": "^5.5.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"n8n-workflow": "*"
|
|
58
|
+
}
|
|
59
|
+
}
|