Хороші ідеї, витрати й важливі дрібниці рідко приходять у зручний момент. Зазвичай це трапляється за кермом, між зустрічами, у черзі або дорогою на об’єкт. Відкрити нотатки незручно, друкувати довго, а “запам’ятаю потім” майже завжди закінчується втратою контексту. Саме тут голос працює краще за текст — але тільки якщо він не застрягає у Telegram назавжди.

Смартфон з інтерфейсом Telegram, бот перетворює аудіо-нотатку на текст
Смартфон з інтерфейсом Telegram, бот перетворює аудіо-нотатку на текст

Робоча концепція проста: бот бере ваше voice-повідомлення, перетворює його на текст, витягує із фрази сенс і записує все у Google Sheets уже в нормальному табличному вигляді. Тобто перекладає з “людської” мови в “системну”. Сказали: “Закинь 800 гривень на маркетинг у Фейсбуці” — отримали рядок [Дата] | Маркетинг | 800 | Facebook.

Як виглядає технологічний ланцюжок

Як виглядає технологічний ланцюжок
Як виглядає технологічний ланцюжок

Сценарій складається з чотирьох вузлів:

  • ви записуєте voice у Telegram
  • бот отримує file_id і забирає файл із Telegram
  • аудіо йде в Whisper API для транскрибації
  • текст іде в gpt-4o-mini, який повертає структуровані дані
  • готовий запис летить у Google Sheets

Тут важлива одна практична деталь: Telegram voice часто приходить у форматі OGG/OPUS, а транскрибація OpenAI працює з іншим набором форматів. Тому в продакшн-ланцюжку не завжди можна обійтися “прямою відправкою”; інколи потрібна проміжна конвертація в wav або webm. Це не проблема архітектури, а просто технічний шов, який треба врахувати одразу.

Чому цей сценарій корисний не лише для фінансів

Перший очевидний кейс — облік витрат. Але на практиці цей підхід добре лягає і на задачі, і на контент, і на польові нотатки керівника. Наприклад, для нішевого проєкту про LED освітлення таким ботом можна швидко фіксувати теми статей, ідеї порівнянь, списки моделей чи технічні спостереження просто з телефону, без ручного перенесення в таблицю потім.

Тобто таблиця перестає бути місцем, куди ви “доробляєте дані ввечері”, і стає живим інтерфейсом для фіксації того, що вже прозвучало.

Як отримати voice-файл з Telegram

Як отримати voice-файл з Telegram
Як отримати voice-файл з Telegram

У Telegram Bot API для голосових повідомлень ви працюєте через msg.voice.file_id. Далі бот отримує пряме посилання на файл через getFileLink(), завантажує його у тимчасову папку і передає на наступний крок пайплайна. Якщо формат не підходить для Whisper, ви проганяєте файл через ffmpeg і вже після цього віддаєте в OpenAI.

Нижче — базовий ESM-приклад для Node.js. Він показує повний цикл: отримання voice, транскрибацію, витяг категорії та суми через GPT і запис у Google Sheets.

import fs from "fs";
import path from "path";
import os from "os";
import { promisify } from "util";
import { execFile } from "child_process";
import TelegramBot from "node-telegram-bot-api";
import OpenAI from "openai";
import { google } from "googleapis";

const execFileAsync = promisify(execFile);
const bot = new TelegramBot(process.env.TELEGRAM_BOT_TOKEN, { polling: true });
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

bot.on("voice", async (msg) => {
  try {
    const fileId = msg.voice.file_id;
    const fileLink = await bot.getFileLink(fileId);

    const oggPath = path.join(os.tmpdir(), `${fileId}.ogg`);
    const wavPath = path.join(os.tmpdir(), `${fileId}.wav`);

    const audioResponse = await fetch(fileLink);
    const audioBuffer = Buffer.from(await audioResponse.arrayBuffer());
    fs.writeFileSync(oggPath, audioBuffer);

    await execFileAsync("ffmpeg", [
      "-y",
      "-i", oggPath,
      "-ar", "16000",
      "-ac", "1",
      wavPath
    ]);

    const transcription = await openai.audio.transcriptions.create({
      file: fs.createReadStream(wavPath),
      model: "whisper-1"
    });

    const voiceText = transcription.text;

    const aiData = await getStructuredData(voiceText);
    await addToSheets(aiData);

    await bot.sendMessage(
      msg.chat.id,
      `🤖 Почув: "${voiceText}". Записав у таблицю як ${aiData.category} / ${aiData.amount}.`
    );

    fs.unlinkSync(oggPath);
    fs.unlinkSync(wavPath);
  } catch (error) {
    console.error(error);
    await bot.sendMessage(msg.chat.id, "Не вдалося обробити голосове повідомлення.");
  }
});

async function getStructuredData(text) {
  const completion = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    response_format: { type: "json_object" },
    temperature: 0.1,
    messages: [
      {
        role: "system",
        content: "Ти витягуєш із тексту дату, категорію, суму, канал та короткий опис. Відповідай тільки JSON."
      },
      {
        role: "user",
        content: `Перетвори фразу у JSON з полями date, category, amount, channel, note: ${text}`
      }
    ]
  });

  return JSON.parse(completion.choices[0].message.content);
}

async function addToSheets(data) {
  const auth = new google.auth.GoogleAuth({
    keyFile: process.env.GOOGLE_SERVICE_ACCOUNT_JSON,
    scopes: ["https://www.googleapis.com/auth/spreadsheets"]
  });

  const sheets = google.sheets({ version: "v4", auth });
  await sheets.spreadsheets.values.append({
    spreadsheetId: process.env.SPREADSHEET_ID,
    range: "Sheet1!A:E",
    valueInputOption: "USER_ENTERED",
    requestBody: {
      values: [[data.date, data.category, data.amount, data.channel, data.note]]
    }
  });
}

Будьте обачні, використовуючи код: для цього сценарію вам потрібні змінні середовища, доступ до Google Sheets API і встановлений ffmpeg на сервері або локальній машині.

Як це виглядає на практиці

У реальному використанні вся магія не в транскрибації, а в другому кроці — у витягу сенсу. Саме він відділяє “бота-диктофон” від робочого інструмента. Якщо менеджер каже: “Запиши 1200 на пальне, поїздка до складу”, система має повернути не просто текст, а структуру: дата, категорія, сума, коментар. Те саме працює для задач: “Передзвонити постачальнику завтра о 12” або “Підготувати КП для нового ліда”.

Whisper тут зручний тим, що знімає бар’єр між думкою та фіксацією. Ви не відкриваєте форму, не шукаєте потрібну вкладку і не думаєте, куди саме клацнути. Ви просто говорите. А далі пайплайн сам переводить фразу в структуровані дані.

Що це дає керівнику на практиці

Ваша таблиця тепер має вуха
Ваша таблиця тепер має вуха

Цінність такого бота не в тому, що він “уміє розпізнавати голос”. Це технічна деталь. Реальна користь у тому, що він прибирає тертя. Менше втрачених витрат. Менше забутих задач. Менше голосових, які зависли в месенджері без жодного шансу потрапити в систему.

Якщо мислити інженерно, це не просто Telegram-бот, а легкий voice-to-sheet інтерфейс поверх вашого операційного контуру. І саме такі дрібні інтерфейси найчастіше дають найкращий ROI: не тому, що вони складні, а тому, що ними реально користуються щодня.

Майбутнє тут не в “розумному боті”, а в тому, що між ідеєю, витратою чи задачею і записом у систему більше немає ручного бар’єра. Ваша таблиця тепер має вуха.