✨ Особенности
- ⚡ Асинхронный поиск музыки
- 🔍 Поддержка нескольких источников
- 🛠️ Простое расширение новыми движками
- 📦 Легкая интеграция в проекты
- 🚀 Быстрая установка через pip
- 🖥️ TUI (Terminal User Interface) с поиском, прослушиванием и скачиванием
📦 Установка
Для установки библиотеки можно использовать pip:
pip install msoc
Так же можно установить из исходников:
git clone https://github.com/paranoik1/msoc.git
cd MSOC
pip install .
🚀 Использование
🖥️ TUI (Textual User Interface)
Запустите TUI для интерактивного поиска, прослушивания и скачивания музыки:
msoc --tui
# or
python -m msoc --tui
TUI позволяет:
- Искать треки по запросу
- Прослушивать треки через ffmpeg (автоопределение PulseAudio/PipeWire)
- Скачивать треки в текущую директорию
- Видеть продолжительность треков
Требование: для работы TUI нужен ffmpeg в системе. При разработке использовался
ffmpeg version n8.1.2.
Эксперименты с оптимизацией
В процессе разработки я экспериментировал с тем, как уменьшить количество сетевых запросов при проигрывании. Для тестов использовал wondershaper — под Linuх он позволяет искусственно резать пропускную способность интерфейса, что удобно симулировать слабый интернет.
Сейчас воспроизведение выглядит так:
- ffmpeg скачивает трек во временную папку (
-c:a copy— без перекодирования, просто сохраняет поток как есть). - Второй ffmpeg читает уже локальный файл, декодирует в PCM и отправляет в sounddevice.
Загрузка и воспроизведение работают в разных потоках, поэтому не блокируют друг друга — можно начать слушать, не дожидаясь полной загрузки.
Что хочется доделать: сейчас длительность и другие метаданные вытаскиваются
отдельным вызовом ffprobe (по сути — ещё один запрос к недокачанному файлу).
Планирую парсить stderr первого ffmpeg, чтобы получать ту же информацию
без лишних походов в сеть.
Как работает скачивание
Когда пользователь нажимает Download, логика такая:
- Если трек уже загружен во временную папку (докачался во время прослушивания) — просто копируем оттуда в текущую директорию. Никаких новых запросов в сеть.
- Если трек прямо сейчас играет, но ещё не докачался — ждём, пока
фоновый ffmpeg закончит, и копируем. Пользователь видит
...на кнопке. - Если трек не играл и не загружался — ffmpeg скачивает напрямую
(
-c:a copy), сохраняя в текущую папку.
💻 В консоле
Можно протестировать пакет обычным скриптом:
msoc <query or empty>
# or
python -m msoc <query or empty>
При запуске будет выведена информация о найденных треках: Name, Artist, URL, Engine (название движка) и Meta (дополнительные метаданные).
⌨️ В коде
Импортируйте модуль msoc и используйте функцию search() для поиска музыки:
from msoc import search
import asyncio
async def main():
query = input("Запрос: ")
async for sound in search(query):
print(f"Name: {sound.title}\nArtist: {sound.artist}\nURL: {sound.url}")
print("================================================")
asyncio.run(main())
Функция search() принимает поисковый запрос и опциональный параметр mode (по умолчанию Mode.Fast):
Mode.Fast— каждый движок выполняет только первый запрос (одна страница результатов).Mode.Full— движок пытается собрать все страницы результатов через функциюsearch_full. Если движок не реализуетsearch_full, используется обычныйsearchс предупреждением.
from msoc import search, Mode
async for sound in search("query", mode=Mode.Full):
...
В CLI режим задаётся флагом --mode:
msoc --tui --mode full
msoc "query" --mode fast
🎶 Класс Sound
Класс Sound содержит информацию о песне.
| Поле | Тип | Описание |
|---|---|---|
title |
str |
Название песни |
url |
str |
Ссылка на скачивание |
artist |
str | None |
Исполнитель (опционально) |
meta |
dict[str, Any] |
Дополнительные метаданные (по умолчанию {}) |
_engine |
str | None |
Движок-источник, заполняется автоматически |
🔌 Реализованные движки поиска
В настоящее время библиотека MSOC поддерживает следующие движки поиска:
- zaycev_net: Поиск на сайте zaycev.net
- hitmo: Поиск на сайте rus.hitmotop.com - реализован на основе данного кода от Ushiiro82
- muzbomb: Поиск на сайте muzbomb.net - создан takilow
Движки загружаются автоматически при импорте пакета msoc.
❌ Exceptions
Библиотека MSOC определяет следующие исключения:
LoadedEngineNotFoundError: Выбрасывается, когда движок поиска не был найден в загруженных движках.
🛠️ Создание своих поисковых движков
Для создания собственных поисковых движков на Python вы можете использовать следующий подход:
-
Создайте новый Python-файл для вашего поискового движка:
- Например, создайте файл
my_search_engine.py.
- Например, создайте файл
-
Определите асинхронную функцию
search(query), которая будет реализовывать поисковый алгоритм:- Реализуйте логику поиска, взаимодействуя с API или веб-страницами источников, которые вы хотите использовать.
- Можете использовать библиотеки, такие как
aiohttp,beautifulsoup4и другие, для выполнения HTTP-запросов и парсинга HTML-страниц.
Для поддержки режима Mode.Full движок может реализовать функцию search_full(query) с той же сигнатурой, что и search. Она должна проходить по всем страницам результатов. Если search_full не определена, Mode.Full просто использует search (одна страница).
Функция search внутри движка должна возвращать генератор объектов Sound.
Пример реализации функции search(query) в my_search_engine.py:
import aiohttp
from bs4 import BeautifulSoup
from msoc.sound import Sound
async def search(query: str):
async with aiohttp.ClientSession() as session:
async with session.get(f"https://example.com/search?q={query}") as response:
html = await response.text()
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all("div", class_="search-result"):
name = item.find("h3").get_text(strip=True)
artist = item.find("span", class_="artist").get_text(strip=True)
url = item.find("a").get("href")
yield Sound(name, url, artist)
- Подключите ваш поисковый движок к системе:
from msoc import register_engine, get_engines
import my_search_engine
register_engine("my_search_engine", my_search_engine)
print(get_engines())
- Замените
my_search_engineна название вашего python файла. - Далее вызываем
get_engines(), чтобы удостовериться, что движок был успешно загружен
- Теперь при запуске основной
searchфункции, ваш движок будет автоматически загружен и использован для поиска песен
ℹ️ P.S 1
Если вам нужно подключить поисковой движок, файл которого находится не в текущей папке проекта, можете воспользоваться встроенным python пакетом importlib
from msoc import register_engine
from importlib import util
spec = util.spec_from_file_location("my_search_engine", "/path/to/python/file/my_search_engine.py")
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
register_engine("my_search_engine", module)
ℹ️ P.S 2
Если вам не нужен какой либо поисковой движок, используй unload_search_engine для его удаления из загруженных:
from msoc import unload_search_engine, engines
unload_search_engine("my_search_engine")
print(engines())
ℹ️ P.S 3 — Проверка доступности сервиса
Проверка доступности теперь лежит на самом движке. Если сайт недоступен, движок должен сам обработать ошибку в search() (логирование, возврат пустого результата и т.д.). msoc не делает отдельного запроса для проверки — лишний сетевой вызов только замедляет поиск. Переменная URL в модуле движка теперь используется только как константа внутри самого движка.
🤝 Contribution
Если вы хотите внести свой вклад в развитие библиотеки MSOC, вы можете:
- 🐞 Сообщить об ошибках или предложить новые функции
- 🎛️ Разработать и добавить новые движки поиска
- 📖 Улучшить документацию
- 🔧 Исправить существующие проблемы
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file msoc-0.3.0.tar.gz.
File metadata
- Download URL: msoc-0.3.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
462b09c06262ea8ecef09304929c43d1a00463486359fcfe853fad318d870cfc
|
|
| MD5 |
4b9c74d46bbcdf3946955704a9639142
|
|
| BLAKE2b-256 |
40361c54e7e0d3871a639c81e9b90703a7aba0e9617388b4bbbcf52b0943edaf
|
File details
Details for the file msoc-0.3.0-py3-none-any.whl.
File metadata
- Download URL: msoc-0.3.0-py3-none-any.whl
- Upload date:
- Size: 25.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02a024a9b5cab4876f19076a01be3cb199f5fda2fc311e81bd143a74f6df4b38
|
|
| MD5 |
2aacdcf582aabec5ee636afd332d0206
|
|
| BLAKE2b-256 |
898cc9e99124bc64bc2f4402123ef9878a4932b07cbfa0f261332ab12cb0fc42
|