Как создать телеграмм-бота, подобного Shazam, с использованием Python

Когда вы слушаете музыку на улице, например, в баре или магазине, и она вам действительно нравится, разве вам не интересно, как называется песня и имя певца?

Это случалось со мной много раз, и есть только одно решение. Shazam. Загрузите его и нажмите на всплывающую кнопку, чтобы определить музыку.

В этой статье мы собираемся создать аналогичное приложение, чтобы искать песню и исполнителя. Быстрый и простой способ разработать этот проект в области Data Science – создать Telegram-бота на Python.

Когда вы слушаете музыку, вы записываете звук. Этот бот переведёт аудио в текст и найдёт для вас название песни и исполнителя. Давайте начнем!

Часть 1: Создание Telegram-бота с помощью Python

Как создать телеграмм-бота, подобного Shazam, с использованием Python

Этот урок будет разделён на две части. В первой части мы сосредоточимся на создании telegram-бота, который сможет определить песню и выдать информацию о ней и её исполнителе. Далее мы развернём telegram-бота для fly.io , которая представляет собой одну из многих платформ, позволяющих создавать, запускать и масштабировать приложения в облаке.

  • Требования
  • Установка библиотек
  • Первые шаги по созданию бота для Telegram
  • Расшифровка аудиозаписи песни
  • Получение информации о песне
Требования

Перед началом программирования на Python необходимо выполнить несколько шагов.

  • Зайдите в Telegram, найдите @botfather и нажмите на первый появившийся результат.
Как создать телеграмм-бота, подобного Shazam, с использованием Python
  • Нажмите кнопку “Пуск”, чтобы начать диалог с BotFather.
Как создать телеграмм-бота, подобного Shazam, с использованием Python
  • Напишите команду /newbot и следуйте инструкциям, предложенным на скриншоте. После создания бота вы получите токен от BotFather, позволяющий вам получить доступ к Telegram API.
Как создать телеграмм-бота, подобного Shazam, с использованием Python
  • Введите имя вашего telegram-бота.
Как создать телеграмм-бота, подобного Shazam, с использованием Python
Установка библиотек

Прежде всего, установите библиотеку python, которая позволяет создать telegram-бота с помощью нескольких строк кода. Она называется pyTelegramBotAPI.

pip install pyTelegramBotAPI

Чтобы расшифровать аудио, я собираюсь использовать Steamship API. Перед установкой пакета вам необходимо установить nodej. На Windows вам нужно установить его отсюда и добавить путь в переменную окружения PATH, в то время как в ubuntu вам нужно ввести две строки кода:

sudo apt install nodejs
sudo apt install npm

После этого вы, наконец, сможете установить Steamship CLI в свою IDE Python.

pip install steamship
npm install -g @steamship/cli
ship login

Как только он будет установлен, мы перейдём к третьему API, который позволяет нам находить песню из аудио. Это возможно, получив доступ к результатам поиска Google через этот API, называемый SerpApi.

pip install google-search-results
Первые шаги по созданию бота для Telegram

Как только вы получили токен API Telegram и создали Telegram-бота, который должен появиться в вашем приложении Telegram, мы можем начать изучать pyTelegramBotAPI, который предоставляет реализации на Python для создания Telegram-бота используя несколько строк кода.

Существует много других различных библиотек python, которые позволяют создавать Telegram-ботов, но поскольку я нашел много руководств, в которых использовалась эта библиотека, и документация была хорошо составлена, я выбрал её для своего небольшого проекта.

import os
import json
...
from steamship import Steamship, TaskState
import telebot
from serpapi import GoogleSearch

f = open("cred.json", "rb")
params = json.load(f)
BOT_TOKEN = params['BOT_TOKEN']
bot = telebot.TeleBot(BOT_TOKEN)

У нас есть файл cred.json, содержащий токен бота и ключи API для Steamship и SerpApi:

{
"BOT_TOKEN":<your_bot_token>,
"API_KEY":<your_serpapi_key>,
"STEAM_API_KEY":<your_steamship_api_key>
 }

В строке 11 мы просто создаём экземпляр TeleBot, который представляет собой класс, предоставляющий функции для обработки сообщений в Telegram. Например, давайте определим обработчик сообщений, который возвращает сообщение “Вставьте аудио вашей песни”, если вы пишете в чате /start или /hello.

@bot.message_handler(commands=['start', 'hello'])
def send_welcome(message):
    bot.reply_to(message, "Insert the audio of your song!")

bot.infinity_polling()

В конце кода мы запускаем бота с помощью bot.infinity_polling()

Как создать телеграмм-бота, подобного Shazam, с использованием Python

У вас должен получиться аналогичный результат, как на скриншоте выше, после запуска python bot.py на терминале.

После функции send_welcome, мы можем определить другую функцию, называемую telegram_bot, которая будет работать с аудиофайлами типа “voice”.

@bot.message_handler(content_types=['voice'])
def telegram_bot(message,bot_token=params["BOT_TOKEN"]):
    # insert audio
    file_info = bot.get_file(message.voice.file_id)
    # extract telegram's url of the audio 
    audio_url = 'https://api.telegram.org/file/bot{}/{}'.format(bot_token,file_info.file_path)

bot.infinity_polling()

Мы заинтересованы в получении общедоступного URL вашего аудиофайла, отправленного боту. Чтобы проверить правильность URL-адреса, скопируйте следующий путь, заменив токен бота и путь к файлу в вашем браузере. Если это сработает, он должен загрузить аудио на ваш локальный компьютер.

https://api.telegram.org/file/bot<bot_token>/<file_path>

Последняя операция, которую нам нужно выполнить – это преобразование аудио из OGA в формат MP3. Это важный шаг, поскольку файл OGA не поддерживается для транскрипции.

def convert_oga_to_mp3(audio_url):
    file = requests.get(audio_url)
    urllib.request.urlretrieve(audio_url,'audio.oga')
    subprocess.run(["ffmpeg", "-i", 'audio.oga', 'audio.mp3'])
    data = open('audio.mp3', 'rb')

def get_url_mp3(bot_token,message):
    bot.reply_to(message, 'Searching song...')
    data = open('audio.mp3', 'rb')
    ret_msg = bot.send_voice(message.chat.id,data)
    file_info = bot.get_file(ret_msg.voice.file_id)
    audio_url = 'https://api.telegram.org/file/bot{}/{}'.format(bot_token,file_info.file_path)
    return audio_url
  
@bot.message_handler(content_types=['voice'])
def telegram_bot(message,bot_token=params["BOT_TOKEN"]):
    # insert audio
    file_info = bot.get_file(message.voice.file_id)
    # extract telegram's url of the audio 
    audio_url = 'https://api.telegram.org/file/bot{}/{}'.format(bot_token,file_info.file_path)
    convert_oga_to_mp3(audio_url)
    audio_url = get_url_mp3(bot_token,message)
    
bot.infinity_polling()

Чтобы преобразовать аудио в mp3-файл, мы собираемся использовать оболочку ffmpeg, которая позволяет конвертировать различные аудиофайлы с помощью командной строки. Прежде чем воспользоваться ей, вам необходимо будет её установить. Если вы работаете на Windows, ознакомьтесь с этим руководством, в котором показаны все шаги, в то время как на Linux вам нужна только командная строка sudo apt install ffmpeg.

После преобразования, достигнутого в строке 4 в функцию convert_oga_to_mp3, нам нужно снова извлечь URL нового аудиофайла, который в конце будет иметь другой формат.

Расшифровка аудиозаписи песни

Теперь мы подошли к самой интересной части руководства, которая помогает нам достичь целей telegram-бота. Прежде чем идти дальше, войдите сюда, чтобы получить ключ API. Во-первых, мы хотим расшифровать аудио с помощью Steamship API. Функция transcribe_audio принимает в качестве входных данных URL-адрес аудио, полученный ранее, и экземпляр Steamship, который представляет собой класс, предоставляющий функции и методы для многих приложений искусственного интеллекта. В данном случае речь идет о транскрипции звука.

# transcribe audio with Steamship's API
def transcribe_audio(audio_url: str, ship: Steamship):
    instance = ship.use("audio-markdown", "audio-markdown-crows-v27")
    transcribe_task = instance.invoke("transcribe_url", url=audio_url)
    task_id = transcribe_task["task_id"]
    status = transcribe_task["status"]

    retries = 0
    while retries <= 100 and status != TaskState.succeeded:
        response = instance.invoke("get_markdown", task_id=task_id)
        status = response["status"]
        if status == TaskState.failed:
            print(f"[FAILED] {response}['status_message']")
            break

        print(f"[Try {retries}] Transcription {status}.")
        if status == TaskState.succeeded:
            break
        time.sleep(2)
        retries += 1

    markdown = response["markdown"]
    return markdown
    
 ...
 
 @bot.message_handler(content_types=['voice'])
def telegram_bot(message,bot_token=os.getenv("BOT_TOKEN")):
    client = Steamship(api_key=os.getenv("STEAM_API_KEY"))
    ...
    markdown = transcribe_audio(audio_url, client)
    bot.reply_to(message, markdown)
 

bot.infinity_polling()

Код может быть обобщён несколькими строками:

  • В строке 3 мы указываем, что собираемся использовать пакет audio_markdown для транскрибирования аудио, а затем генерировать выходные данные Markdown.
  • В следующей строке мы вызываем метод transcribe_url, вызывая invoke. Нам также нужно передать наш URL-адрес аудио.
  • В середине функции мы вызываем метод get_markdown, который позволит нам получить транскрипцию аудио. Количество повторных попыток ограничено 100, чтобы избежать бесконечных циклов в случае, если это не увенчается успехом.
  • Функция возвращает транскрипцию в конце, и мы получаем результирующий текст в telegram-боте.
Получение информации о песне

После получения транскрипции мы переходим к следующему шагу, который заключается в обнаружении названия и исполнителя песни. Это возможно реализовать с помощью SerpApi, который представляет собой API, позволяющий получать доступ к результатам Google и других веб-сайтов.

## search the trascription on Google using SerpAPI 
def search_words(words):
    params_serp = {
    "q": words,
    "hl": "en",
    "gl": "us",
    "google_domain": "google.com",
    "api_key": params['API_KEY']

    }
    search = GoogleSearch(params_serp)
    results = search.get_dict()
    if 'organic_results' in results.keys():
        if 'title' in results['organic_results'][0].keys():
            return results['organic_results'][0]['title']
        else:
            return ''
    else:
        return ''
        
@bot.message_handler(content_types=['voice'])
def telegram_bot(message,bot_token=params["BOT_TOKEN"]):
    ...
    client = Steamship(api_key=params["STEAM_API_KEY"])
    markdown = transcribe_audio(audio_url, client)
    bot.reply_to(message, markdown)
    result = search_words(markdown)
    ...
    if result == '':
        bot.reply_to(message, 'Song not found!')
    else:
         bot.reply_to(message, result)
         
bot.infinity_polling() 

Нам нужно передать словарь в GoogleSearch с параметрами, такими как слова песни, ключ API SerpApi. Мы собираемся получить результаты от Google. Он возвращает вывод JSON, который может быть преобразован в словарь Python, чтобы получить доступ к информации. После этого отправителю будет отправлено текстовое сообщение.

Часть 2: Развёртывание Telegram-бота для Fly.io

До сих пор мы реализовывали процесс работы чат-бота, который произойдёт, если пользователь запустит следующую команду:

python bot.py

Но это означает, что бот будет работать только тогда, когда вы запустите этот код, а это непрактично. Предпочтительно, чтобы telegram-бот был всегда доступен и люди могли его опробовать.

По этой причине нам необходимо развернуть Telegram-бота. Сначала я хотел использовать Heroku, которая является ещё одной платформой с закрытым исходным кодом для развёртывания приложений, но она больше не предлагает бесплатный доступ.

Итак, я выбрал Fly.io как облачный сервис, потому что он предоставляет бесплатный тарифный план и имеет хорошую документацию.

  • Создание requirements.txt и Dockerfile
  • Подключение к Fly.io
  • Запуск приложения
  • Развёртывание приложения
1. Создание requirements.txt и Dockerfile

Чтобы запустить его в производство, нам нужен файл requirements.txt , который содержит все зависимости python. Он может быть автоматически создан путём запуска командной строки pipreqs в вашем терминале. Вы должны установить pipreqs, чтобы заставить командную строку работать. Это пакеты python, требуемые проектом:

google_search_results==2.4.1
pyTelegramBotAPI==4.9.0
python-dotenv==0.21.1
requests==2.28.1
steamship==2.3.5

В дополнение к этому файлу нам также нужен другой файл, называемый Dockerfile, который должен быть таким:

FROM python:3.10.2

WORKDIR /bot

COPY requirements.txt /bot/
RUN pip install -r requirements.txt
RUN apt-get update
RUN apt-get install ffmpeg -y
RUN apt-get install nodejs -y
RUN apt-get install npm -y

COPY . /bot

CMD python bot.py
2. Подключение к Fly.io

Третье требование – это установка flyctl, командной строки, которая позволит развернуть наше приложение. Вы можете найти инструкцию здесь. Она может отличаться в зависимости от вашей операционной системы.

Если вы не создали Fly.io учетная запись, вам необходимо сделать это, запустив командную строку:

flyctl auth signup

В случае, если у вас уже есть учетная запись, вам нужно только войти в систему, скопировав в терминал следующую строку:

fly auth login
3. Запуск приложения

Чтобы начать работу с этим проектом, мы можем ввести в командную строку следующий код:

flyctl launch

Он запросит у вас следующую информацию:

  • Напишите название приложения.
  • Выберите регион для развёртывания.
  • Хотите ли вы настроить базу данных Postgresql. В нашем случае ответ – нет.
  • Хотите ли вы создать резервную базу данных Redis прямо сейчас. В нашем случае ответ – нет.
  • Хотите ли вы развернуть приложение прямо сейчас. На данный момент ответ – “нет”. Мы сделаем это позже.

Перед развёртыванием приложения я также решил использовать функциональность, предоставляемую fly.io . Как вы, возможно, знаете, учётные данные являются конфиденциальными, и вы можете предпочесть не раскрывать свои секреты никому, кроме себя. Это возможно, связав следующие командные строки:

flyctl secrets set BOT_TOKEN=<your_bot_token>
flyctl secrets set STEAM_TOKEN=<your_steam_api>
flyctl secrets set API_KEY=<your_serpapi_key>

После запуска этих командных строк необходимо изменить код python. Мы больше не используем файл JSON с учётными данными, которые хранятся непосредственно на платформе fly.io. Например, таким образом мы можем получить доступ к токену Telegram-бота:

from dotenv import load_dotenv

load_dotenv()
bot = telebot.TeleBot(os.getenv("BOT_TOKEN"))

Вам нужно сделать то же самое для других ключей API. Вы можете проверить список командных строк с помощью следующей команды:

flyctl secrets list
4. Развёртывание приложения

Наконец-то мы “достигли вершины Эвереста”! Ещё одна командная строка, и всё готово:

flyctl deploy

Таким образом, наш контейнер docker с telegram-ботом собран и развёрнут. Код будет запущен в облаке, а не на локальном компьютере. Теперь telegram-бот будет работать для всех!

Заключительные мысли:

Я надеюсь, вам понравился этот проект в области Data Science. В Интернете доступно множество ресурсов, которые позволяют получить всё, что вы хотите. Вам нужны только творческий подход, терпение и усердная работа. Если у вас есть какой-либо из этих ингредиентов, нет никаких ограничений на то, что вы можете сделать. Код на GitHub находится здесь. Спасибо вам за чтение!

+1
1
+1
2
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *