<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>КББ</title><subtitle>Ёмко об IT, фото, фильмах, книгах, музыке, играх и гик-культуре</subtitle><author><name>КББ</name></author><id>https://teletype.in/atom/beaverclan</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/beaverclan?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/beaverclan?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-08-03T22:58:33.584Z</updated><entry><id>beaverclan:youtubemcp</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/youtubemcp?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>YouTube MCP: скачиваем видео и вшиваем субтитры</title><published>2026-07-02T19:15:00.550Z</published><updated>2026-07-02T19:15:00.550Z</updated><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/youtubemcp/logo.webp&quot;&gt;Я часто скачиваю видео с ютуба, чтобы перекинуть в телеграм канал. В телеграме видео можно глянуть и без звука, да и принято щас так, как в рилсах кароче. Да и ролики бывают не на славянских языках, вшивать их каждый раз руками это эт лень.</summary><content type="html">
  &lt;figure id=&quot;hPPt&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/youtubemcp/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;зачем-это-нужно&quot;&gt;Зачем это нужно&lt;/h2&gt;
  &lt;p id=&quot;Mevx&quot;&gt;Я часто скачиваю видео с ютуба, чтобы перекинуть в телеграм канал. В телеграме видео можно глянуть и без звука, да и принято щас так, как в рилсах кароче. Да и ролики бывают не на славянских языках, вшивать их каждый раз руками это эт лень.&lt;/p&gt;
  &lt;p id=&quot;YBy2&quot;&gt;Я запилил эмсипи-сервер для оупенкода, который делает всё одной командой: скачивает видео, достаёт субтитры (русские или английские), переводит их на русский прямо в чате и вшивает в видео. Никаких апи-ключей, никаких внешних сервисов — только yt-dlp, ffmpeg и сам оупенкод.&lt;/p&gt;
  &lt;h2 id=&quot;как-это-работает&quot;&gt;Как это работает&lt;/h2&gt;
  &lt;p id=&quot;bhRJ&quot;&gt;Процесс выглядит так:&lt;/p&gt;
  &lt;ol id=&quot;YYZn&quot;&gt;
    &lt;li id=&quot;5OTk&quot;&gt;Спрашиваю у оупенкода «скачай видос с ютуба, вшей субтитры»&lt;/li&gt;
    &lt;li id=&quot;e9lP&quot;&gt;Оупенкод спрашивает у меня ссылку и куда сохранить&lt;/li&gt;
    &lt;li id=&quot;7fY1&quot;&gt;Эмсипи сервер скачивает видео в 480p (для телеграма самое то)&lt;/li&gt;
    &lt;li id=&quot;2kFi&quot;&gt;Сервер достаёт субтитры — сперва русские если есть, если нет — английские&lt;/li&gt;
    &lt;li id=&quot;V0zR&quot;&gt;Если субтитры на английском, оупенкод переводит их на русский прямо в диалоге&lt;/li&gt;
    &lt;li id=&quot;3v7G&quot;&gt;Ффмпег вшивает субтитры в видео&lt;/li&gt;
    &lt;li id=&quot;DF33&quot;&gt;Готовый файл лежит в ~/Downloads&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;1rLE&quot;&gt;Всё это занимает пару минут и не требует ни одной команды в терминале.&lt;/p&gt;
  &lt;h2 id=&quot;архитектура&quot;&gt;Архитектура&lt;/h2&gt;
  &lt;p id=&quot;D4Cf&quot;&gt;Система состоит из трёх частей:&lt;/p&gt;
  &lt;h3 id=&quot;1-эмсипи-сервер&quot;&gt;1. Эмсипи-сервер&lt;/h3&gt;
  &lt;p id=&quot;vPPl&quot;&gt;Пайтон-скрипт на FastMCP с четырьмя инструментами:&lt;/p&gt;
  &lt;ul id=&quot;Fa4E&quot;&gt;
    &lt;li id=&quot;keIO&quot;&gt;&lt;code&gt;download_video&lt;/code&gt; — скачивает 480p через yt-dlp&lt;/li&gt;
    &lt;li id=&quot;DWpC&quot;&gt;&lt;code&gt;extract_subs&lt;/code&gt; — достаёт субтитры (с авто-субтитрами как запасной вариант)&lt;/li&gt;
    &lt;li id=&quot;UUmo&quot;&gt;&lt;code&gt;save_subs&lt;/code&gt; — сохраняет переведённые субтитры&lt;/li&gt;
    &lt;li id=&quot;heAf&quot;&gt;&lt;code&gt;burn_subs&lt;/code&gt; — вшивает субтитры через ffmpeg&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;7Nn1&quot;&gt;Сервер лежит в &lt;code&gt;~/.config/opencode/mcp/youtube_mcp_server.py&lt;/code&gt;:&lt;/p&gt;
  &lt;p id=&quot;ZUaA&quot;&gt;&lt;a href=&quot;https://blog.tatarinovms.space/static/scripts/youtubemcp/youtube_mcp_server.py&quot; target=&quot;_blank&quot;&gt;Скачать готовый файл&lt;/a&gt;&lt;/p&gt;
  &lt;h3 id=&quot;2-регистрация-в-оупенкод&quot;&gt;2. Регистрация в оупенкод&lt;/h3&gt;
  &lt;p id=&quot;P2sD&quot;&gt;Добавляем в &lt;code&gt;~/.config/opencode/opencode.jsonc&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;DkZt&quot;&gt;&amp;quot;youtube&amp;quot;: {
  &amp;quot;type&amp;quot;: &amp;quot;local&amp;quot;,
  &amp;quot;command&amp;quot;: [
    &amp;quot;/Users/ваш_юзер/.config/opencode/mcp/venv/bin/python3&amp;quot;,
    &amp;quot;/Users/ваш_юзер/.config/opencode/mcp/youtube_mcp_server.py&amp;quot;
  ]
}
&lt;/pre&gt;
  &lt;h3 id=&quot;3-скилл&quot;&gt;3. Скилл&lt;/h3&gt;
  &lt;p id=&quot;n2As&quot;&gt;Чтобы оупенкод сам понимал когда вызывать инструменты, создаём скилл в &lt;code&gt;~/.opencode/skills/youtube-processor/SKILL.md&lt;/code&gt;:&lt;/p&gt;
  &lt;p id=&quot;QfCc&quot;&gt;&lt;a href=&quot;https://blog.tatarinovms.space/static/scripts/youtubemcp/SKILL.md&quot; target=&quot;_blank&quot;&gt;Скачать готовый файл&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;CiID&quot;&gt;В скилле описана последовательность: спросить ссылку и путь → скачать → достать субтитры → если английские — перевести → вшить → отдать результат.&lt;/p&gt;
  &lt;h2 id=&quot;как-я-перевожу-субтитры-без-апи-ключей&quot;&gt;Как я перевожу субтитры без апи-ключей&lt;/h2&gt;
  &lt;p id=&quot;WwCE&quot;&gt;Самый ленивый момент — перевод. Вместо того чтобы дёргать гугл-транслейт или оплачивать апи, я просто отдаю текст субтитров самому оупенкоду. Он переводит всё в диалоге, сохраняя таймкоды и структуру SRT, сохраняет обратно и передаёт на вшивание. Можно локально конечно, но не у всех есть. Да и в целом зачем лишний шаг.&lt;/p&gt;
  &lt;h2 id=&quot;что-получилось-в-итоге&quot;&gt;Что получилось в итоге&lt;/h2&gt;
  &lt;p id=&quot;V6fM&quot;&gt;Протестировал на видео со &lt;a href=&quot;https://youtu.be/CwVkYFsX5Fw?si=mMc9M0RSAbgWUKtR&quot; target=&quot;_blank&quot;&gt;новостями&lt;/a&gt; на стопгейм, ютуб выдаёт автоматические русские субтитры, так что перевод не понадобился. Видео 8 минут скачалось за 10 секунд, субтитры за 3 секунды, вшивание заняло пару минут. На выходе — mp4 со встроенными субтитрами, готовый для телеграма.&lt;/p&gt;
  &lt;p id=&quot;6HkV&quot;&gt;Если у видео нет русских субтитров, оупенкод скачает английские и переведёт их на русский прямо в диалоге — никаких лишних телодвижений.&lt;/p&gt;
  &lt;h2 id=&quot;особенности&quot;&gt;Особенности&lt;/h2&gt;
  &lt;ul id=&quot;Qb95&quot;&gt;
    &lt;li id=&quot;Z6d5&quot;&gt;Для работы нужен FFMpeg с libass. Если &lt;code&gt;subtitles&lt;/code&gt; фильтр не найден — &lt;code&gt;brew install libass &amp;amp;&amp;amp; brew install homebrew-ffmpeg/ffmpeg/ffmpeg&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;WFwu&quot;&gt;Если субтитров нет вообще — оупенкод спросит, сохранить видео без них или отменить&lt;/li&gt;
    &lt;li id=&quot;ARsU&quot;&gt;Для “возрастных видео” может понадобиться куки браузера&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>beaverclan:markitdownmcp</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/markitdownmcp?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>MarkItDown: конвертируем в макрдаун из оупенкод</title><published>2026-06-28T07:12:17.107Z</published><updated>2026-06-28T07:12:17.107Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/ba/4e/ba4e4551-614b-4657-9af2-4078cac5b400.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/markitdownmcp/logo.webp&quot;&gt;В работе с оупенкодом да и с агентами в целом, постоянно нужно читать документы, пдф файлы, эксель таблицы, презентации и прочие, не очень текстовые форматы. ЭЛЛ’мки хорошо понимают макрдаун, поэтому задача конвертации в маркдаун возникает постоянно. Также таким образом я — набиваю свое хранилище в обсидиан всякими гайдами.</summary><content type="html">
  &lt;figure id=&quot;IH0j&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/markitdownmcp/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;зачем-это-нужно&quot;&gt;Зачем это нужно&lt;/h2&gt;
  &lt;p id=&quot;gIXp&quot;&gt;В работе с оупенкодом да и с агентами в целом, постоянно нужно читать документы, пдф файлы, эксель таблицы, презентации и прочие, не очень текстовые форматы. ЭЛЛ’мки хорошо понимают макрдаун, поэтому задача конвертации в маркдаун возникает постоянно. Также таким образом я — набиваю свое хранилище в обсидиан всякими гайдами.&lt;/p&gt;
  &lt;p id=&quot;PRgd&quot;&gt;Майкрософт выпустила утилиту &lt;a href=&quot;https://github.com/microsoft/markitdown&quot; target=&quot;_blank&quot;&gt;MarkItDown&lt;/a&gt; пайтон библиотеку, которая умеет конвертировать, практически, всё во что угодно в маркдаун:&lt;/p&gt;
  &lt;ul id=&quot;SZhs&quot;&gt;
    &lt;li id=&quot;uOOH&quot;&gt;*.PDF&lt;/li&gt;
    &lt;li id=&quot;1ED0&quot;&gt;*.DOCX&lt;/li&gt;
    &lt;li id=&quot;AS6T&quot;&gt;*.XLSX&lt;/li&gt;
    &lt;li id=&quot;fP1A&quot;&gt;*.PPTX&lt;/li&gt;
    &lt;li id=&quot;fuoC&quot;&gt;HTML&lt;/li&gt;
    &lt;li id=&quot;QWIo&quot;&gt;*.EPUB&lt;/li&gt;
    &lt;li id=&quot;3jRb&quot;&gt;*.XML&lt;/li&gt;
    &lt;li id=&quot;jLHT&quot;&gt;ну и так далее&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;что-такое-mcp-и-как-это-работает&quot;&gt;Что такое MCP и как это работает&lt;/h2&gt;
  &lt;p id=&quot;52le&quot;&gt;MCP (Model Context Protocol) — это стандарт, который позволяет подключать внешние инструменты к эай-ассистентам (в нашем случае — к оупенкод). Через эмсипи мы даём оупенкод возможность выполнять произвольные действия: читать файлы, запускать команды, ходить в эпиай.&lt;/p&gt;
  &lt;p id=&quot;2gMV&quot;&gt;Мы создадим эмсипи сервер, который оборачивает MarkItDown в один простой инструмент &lt;code&gt;convert_to_markdown&lt;/code&gt;. После этого оупенкод сможет сам сконвертировать файл в маркдаун, когда это понадобится.&lt;/p&gt;
  &lt;h2 id=&quot;установка&quot;&gt;Установка&lt;/h2&gt;
  &lt;h3 id=&quot;1-виртуальное-окружение-и-зависимости&quot;&gt;1. Виртуальное окружение и зависимости&lt;/h3&gt;
  &lt;p id=&quot;hnMd&quot;&gt;Макось больше не разрешает ставить пакеты через &lt;code&gt;pip&lt;/code&gt; глобально, поэтому создадим &lt;code&gt;venv&lt;/code&gt; и установим всё туда:&lt;/p&gt;
  &lt;pre id=&quot;tej6&quot;&gt;python3 -m venv ~/.config/opencode/mcp/venv
~/.config/opencode/mcp/venv/bin/pip3 install &amp;#x27;markitdown[all]&amp;#x27; &amp;#x27;mcp[cli]&amp;#x27;
&lt;/pre&gt;
  &lt;p id=&quot;Uz7w&quot;&gt;Разбиваем на составляющие: &lt;code&gt;markitdown[all]&lt;/code&gt; сама библиотека конвертации со всеми опциональными зависимостями, &lt;code&gt;mcp[cli]&lt;/code&gt; Python SDK для создания эмсипи-серверов.&lt;/p&gt;
  &lt;h3 id=&quot;2-скрипт-эмсипи-сервера&quot;&gt;2. Скрипт эмсипи-сервера&lt;/h3&gt;
  &lt;p id=&quot;QufM&quot;&gt;Создаём файл &lt;code&gt;~/.config/opencode/mcp/markitdown_server.py&lt;/code&gt;:&lt;/p&gt;
  &lt;p id=&quot;mSOE&quot;&gt;&lt;a href=&quot;https://blog.tatarinovms.space/static/scripts/markitdownmcp/markitdown_server.py&quot; target=&quot;_blank&quot;&gt;Скачать готовый файл&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;0BOX&quot;&gt;from mcp.server.fastmcp import FastMCP
from markitdown import MarkItDown
import os

mcp = FastMCP(&amp;quot;MarkItDown&amp;quot;)

@mcp.tool()
def convert_to_markdown(file_path: str) -&amp;gt; str:
    &amp;quot;&amp;quot;&amp;quot;Convert any supported file (PDF, DOCX, PPTX, XLSX, HTML, EPUB, XML) to Markdown.&amp;quot;&amp;quot;&amp;quot;
    file_path = os.path.expanduser(os.path.abspath(file_path))
    if not os.path.exists(file_path):
        return f&amp;quot;Error: File not found: {file_path}&amp;quot;
    md = MarkItDown()
    result = md.convert(file_path)
    return result.text_content

if __name__ == &amp;quot;__main__&amp;quot;:
    mcp.run(transport=&amp;quot;stdio&amp;quot;)
&lt;/pre&gt;
  &lt;p id=&quot;Of16&quot;&gt;Здесь мы используем &lt;a href=&quot;https://gofastmcp.com/getting-started/welcome&quot; target=&quot;_blank&quot;&gt;FastMCP&lt;/a&gt; - фреймворк, который берёт на себя всю работу: парсинг JSON-RPC, логирование и т.д. Кароче способ для ленивых.&lt;/p&gt;
  &lt;h3 id=&quot;3-регистрация-в-оупенкод&quot;&gt;3. Регистрация в оупенкод&lt;/h3&gt;
  &lt;p id=&quot;Cn1J&quot;&gt;Добавляем сервер в &lt;code&gt;~/.config/opencode/оупенкод.jsonc&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;79tz&quot;&gt;{
  &amp;quot;$schema&amp;quot;: &amp;quot;https://opencode.ai/config.json&amp;quot;,
  &amp;quot;mcp&amp;quot;: {
    &amp;quot;bb-browser&amp;quot;: { ... },
    &amp;quot;markitdown&amp;quot;: {
      &amp;quot;type&amp;quot;: &amp;quot;local&amp;quot;,
      &amp;quot;command&amp;quot;: [
        &amp;quot;/Users/beaverbloger/.config/opencode/mcp/venv/bin/python3&amp;quot;,
        &amp;quot;/Users/beaverbloger/.config/opencode/mcp/markitdown_server.py&amp;quot;
      ]
    }
  }
}
&lt;/pre&gt;
  &lt;p id=&quot;WeVe&quot;&gt;Готово! оупенкод теперь знает про сервер и будет вызывать его автоматически.&lt;/p&gt;
  &lt;h3 id=&quot;4-скилл-для-оупенкод&quot;&gt;4. Скилл для оупенкод&lt;/h3&gt;
  &lt;p id=&quot;Q8RJ&quot;&gt;Чтобы агент сам знал когда вызывать &lt;code&gt;convert_to_markdown&lt;/code&gt;, создаём скилл. Он подскажет агенту какие форматы поддерживаются и как сохранять результат.&lt;/p&gt;
  &lt;p id=&quot;fBRZ&quot;&gt;Создайте файл &lt;code&gt;~/.opencode/skills/markitdown-converter/SKILL.md&lt;/code&gt;:&lt;/p&gt;
  &lt;p id=&quot;O8Ce&quot;&gt;&lt;a href=&quot;https://blog.tatarinovms.space/static/scripts/markitdownmcp/SKILL.md&quot; target=&quot;_blank&quot;&gt;Скачать готовый файл&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;0SpM&quot;&gt;---
name: markitdown-converter
description: Convert files to Markdown using MCP tool
---

When the user provides a file in a non-text format that needs to be read or converted to Markdown:

1. **Supported formats:** &amp;#x60;.pdf&amp;#x60;, &amp;#x60;.docx&amp;#x60;, &amp;#x60;.xlsx&amp;#x60;, &amp;#x60;.pptx&amp;#x60;, &amp;#x60;.html&amp;#x60;, &amp;#x60;.epub&amp;#x60;, &amp;#x60;.xml&amp;#x60;

2. **Use the &amp;#x60;convert_to_markdown&amp;#x60; MCP tool** with the file path. The path can be:
   - Absolute: &amp;#x60;/Users/name/file.pdf&amp;#x60;
   - With &amp;#x60;~&amp;#x60;: &amp;#x60;~/Downloads/file.docx&amp;#x60;
   - Relative: &amp;#x60;./file.xlsx&amp;#x60;

3. **Save the result** as &amp;#x60;.md&amp;#x60; file next to the original:
   - &amp;#x60;~/Documents/doc.pdf&amp;#x60; → &amp;#x60;~/Documents/doc.md&amp;#x60;
   - &amp;#x60;~/Downloads/report.xlsx&amp;#x60; → &amp;#x60;~/Downloads/report.md&amp;#x60;

4. **Return the path** to the saved &amp;#x60;.md&amp;#x60; file to the user.
&lt;/pre&gt;
  &lt;p id=&quot;gFCf&quot;&gt;Теперь оупенкод сам понимает — файл не текстовый, надо конвертнуть.&lt;/p&gt;
  &lt;h2 id=&quot;как-это-работает&quot;&gt;Как это работает&lt;/h2&gt;
  &lt;p id=&quot;aYDQ&quot;&gt;Когда оупенкоду нужно обработать документ, он:&lt;/p&gt;
  &lt;ol id=&quot;3mNY&quot;&gt;
    &lt;li id=&quot;TNhg&quot;&gt;Видит, что есть инструмент &lt;code&gt;convert_to_markdown&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;H4eY&quot;&gt;Отправляет к эмсипи-запрос с путём к файлу&lt;/li&gt;
    &lt;li id=&quot;M7Bb&quot;&gt;Наш сервер запускает MarkItDown, конвертирует файл&lt;/li&gt;
    &lt;li id=&quot;PrBn&quot;&gt;Возвращает готовый маркдаун&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;2p6Q&quot;&gt;Всё это происходит прозрачно. Оупенкод может вызвать этот инструмент самостоятельно, когда понимает, что файл нужно прочитать.&lt;/p&gt;
  &lt;h2 id=&quot;проверка&quot;&gt;Проверка&lt;/h2&gt;
  &lt;p id=&quot;Yan6&quot;&gt;Перезапустим оупенкод чтобы эмсипи у нас подхватился и просим конвертировать файл пдф в маркдаун. Или просто скажи «прочитай этот файл» — скилл подскажет агенту что делать и тот сам вызовет &lt;code&gt;convert_to_markdown&lt;/code&gt;:&lt;/p&gt;
  &lt;figure id=&quot;DqhG&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/markitdownmcp/1.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;srdc&quot;&gt;
    &lt;li id=&quot;CbzM&quot;&gt;Результат&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;P8A8&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/markitdownmcp/2.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;особенности&quot;&gt;Особенности&lt;/h2&gt;
  &lt;p id=&quot;RroL&quot;&gt;Из коробки библиотека использует встроенные инструменты: pdfplumber для пдф, mammoth для DOCX, openpyxl для XLSX, python-pptx для PPTX, beautifulsoup4 для HTML и т.д.&lt;/p&gt;
  &lt;h2 id=&quot;итого&quot;&gt;Итого&lt;/h2&gt;
  &lt;p id=&quot;sPHJ&quot;&gt;MarkItDown как эмсипи-сервер для оупенкод для меня это полезная комбинация. Юзайте для себя и вашего агента.&lt;/p&gt;

</content></entry><entry><id>beaverclan:duckduckgosearchmcp</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/duckduckgosearchmcp?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>DuckDuckGo Search MCP: веб-поиск для оупенкод</title><published>2026-06-28T07:11:17.514Z</published><updated>2026-06-28T07:11:17.514Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/06/a6/06a66b02-fdf2-416b-ac0e-a28d85af986d.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/duckduckgosearchmcp/logo.webp&quot;&gt;Оупенкод хорош, но у него есть ограничение — он ничего не знает о мире за пределами того, что заложено в моделях которые ты юзаешь в агенте.</summary><content type="html">
  &lt;figure id=&quot;qoTI&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/duckduckgosearchmcp/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;зачем-это-нужно&quot;&gt;Зачем это нужно&lt;/h2&gt;
  &lt;p id=&quot;vwRL&quot;&gt;Оупенкод хорош, но у него есть ограничение — он ничего не знает о мире за пределами того, что заложено в моделях которые ты юзаешь в агенте.&lt;/p&gt;
  &lt;p id=&quot;hsLf&quot;&gt;DuckDuckGo Search MCP сервер решает эту проблему: он даёт оупенкод два инструмента — поиск в вебе и загрузку контента со страниц. Теперь агент может сам сходить в поисковик за актуальной информацией.&lt;/p&gt;
  &lt;p id=&quot;bZVZ&quot;&gt;Чем это отличается от встроенного &lt;code&gt;WebFetch&lt;/code&gt;? WebFetch умеет только загружать контент по конкретному URL. Если агент не знает адрес — он бесполезен. А DuckDuckGo Search MCP добавляет &lt;strong&gt;поиск&lt;/strong&gt;: агент сам находит нужные страницы по запросу, а потом может прочитать их через &lt;code&gt;fetch_content&lt;/code&gt;. То есть это полноценный веб-сёрфинг, а не просто загрузка по известной ссылке.&lt;/p&gt;
  &lt;h2 id=&quot;что-такое-mcp-и-как-это-работает&quot;&gt;Что такое MCP и как это работает&lt;/h2&gt;
  &lt;p id=&quot;fosG&quot;&gt;MCP (Model Context Protocol) — стандарт для подключения внешних инструментов к ИИ-ассистентам. Через эмсипи мы даём оупенкод доступ к произвольным действиям: поиск в интернете, чтение файлов, вызов API.&lt;/p&gt;
  &lt;p id=&quot;qUar&quot;&gt;Мы устанавливаем DuckDuckGo эмсипи сервер, регистрируем его в конфиге оупенкод, и агент получает инструменты &lt;code&gt;search&lt;/code&gt; и &lt;code&gt;fetch_content&lt;/code&gt;. Дальше он сам решает, когда ими воспользоваться.&lt;/p&gt;
  &lt;h2 id=&quot;установка&quot;&gt;Установка&lt;/h2&gt;
  &lt;h3 id=&quot;1-устанавливаем-uv&quot;&gt;1. Устанавливаем uv&lt;/h3&gt;
  &lt;p id=&quot;6RHn&quot;&gt;&lt;code&gt;uv&lt;/code&gt; — менеджер пакетов для Python, через него запускается сервер:&lt;/p&gt;
  &lt;pre id=&quot;MVlv&quot;&gt;curl -LsSf https://astral.sh/uv/install.sh | sh
&lt;/pre&gt;
  &lt;p id=&quot;cY5e&quot;&gt;После установки перезапустите терминал или добавьте &lt;code&gt;~/.local/bin&lt;/code&gt; в PATH.&lt;/p&gt;
  &lt;h3 id=&quot;2-регистрация-в-оупенкод&quot;&gt;2. Регистрация в оупенкод&lt;/h3&gt;
  &lt;p id=&quot;N38i&quot;&gt;Добавляем сервер в &lt;code&gt;~/.config/opencode/opencode.jsonc&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;z8Pw&quot;&gt;{
  &amp;quot;$schema&amp;quot;: &amp;quot;https://opencode.ai/config.json&amp;quot;,
  &amp;quot;mcp&amp;quot;: {
    &amp;quot;bb-browser&amp;quot;: { ... },
    &amp;quot;markitdown&amp;quot;: { ... },
    &amp;quot;ddg-search&amp;quot;: {
      &amp;quot;type&amp;quot;: &amp;quot;local&amp;quot;,
      &amp;quot;command&amp;quot;: [&amp;quot;/Users/beaverbloger/.local/bin/uvx&amp;quot;, &amp;quot;duckduckgo-mcp-server&amp;quot;],
      &amp;quot;env&amp;quot;: {
        &amp;quot;DDG_SAFE_SEARCH&amp;quot;: &amp;quot;MODERATE&amp;quot;,
        &amp;quot;DDG_REGION&amp;quot;: &amp;quot;wt-wt&amp;quot;
      }
    }
  }
}
&lt;/pre&gt;
  &lt;p id=&quot;t878&quot;&gt;Параметры окружения:&lt;/p&gt;
  &lt;ul id=&quot;Xjvr&quot;&gt;
    &lt;li id=&quot;mhF7&quot;&gt;&lt;code&gt;DDG_SAFE_SEARCH&lt;/code&gt; — уровень фильтрации контента: &lt;code&gt;STRICT&lt;/code&gt;, &lt;code&gt;MODERATE&lt;/code&gt; (по умолчанию), &lt;code&gt;OFF&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;u5z8&quot;&gt;&lt;code&gt;DDG_REGION&lt;/code&gt; — регион по умолчанию: &lt;code&gt;us-en&lt;/code&gt;, &lt;code&gt;ru-ru&lt;/code&gt;, &lt;code&gt;wt-wt&lt;/code&gt; (без региона) и т.д.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;pHbC&quot;&gt;Готово! После перезапуска оупенкод подхватит сервер.&lt;/p&gt;
  &lt;h2 id=&quot;инструменты&quot;&gt;Инструменты&lt;/h2&gt;
  &lt;p id=&quot;fNFa&quot;&gt;Сервер предоставляет два инструмента:&lt;/p&gt;
  &lt;h3 id=&quot;searchquery-max_results10-region&quot;&gt;search(query, max_results=10, region=&amp;quot;&amp;quot;)&lt;/h3&gt;
  &lt;p id=&quot;wBcD&quot;&gt;Поиск в DuckDuckGo. Возвращает ссылки с заголовками и сниппетами. Можно указать регион для локализации результатов.&lt;/p&gt;
  &lt;h3 id=&quot;fetch_contenturl-start_index0-max_length8000&quot;&gt;fetch_content(url, start_index=0, max_length=8000)&lt;/h3&gt;
  &lt;p id=&quot;xUoA&quot;&gt;Загрузка и очистка контента со страницы. Убирает навигацию, шапки, подвалы, скрипты — оставляет чистый текст. Поддерживает пагинацию для длинных страниц.&lt;/p&gt;
  &lt;h2 id=&quot;проверка&quot;&gt;Проверка&lt;/h2&gt;
  &lt;p id=&quot;IRoj&quot;&gt;Проверим, как это работает. Прошу оупенкод найти рецепт курута:&lt;/p&gt;
  &lt;figure id=&quot;4eo9&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/duckduckgosearchmcp/1.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Fhu8&quot;&gt;Агент вызывает &lt;code&gt;search(&amp;quot;как готовить курут рецепт&amp;quot;)&lt;/code&gt;, находит ссылки и краткие описания.&lt;/p&gt;
  &lt;p id=&quot;BEm5&quot;&gt;А теперь попросим узнать погоду в Абзаково:&lt;/p&gt;
  &lt;figure id=&quot;jO75&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/duckduckgosearchmcp/2.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;1xLX&quot;&gt;Работает! Агент сам решил, что ему не хватает данных, сходил в интернет и вернул актуальный ответ.&lt;/p&gt;
  &lt;h2 id=&quot;как-это-работает&quot;&gt;Как это работает&lt;/h2&gt;
  &lt;p id=&quot;xCiT&quot;&gt;Когда оупенкоду нужно найти что-то в интернете, он:&lt;/p&gt;
  &lt;ol id=&quot;8lh6&quot;&gt;
    &lt;li id=&quot;cefK&quot;&gt;Видит, что доступен инструмент &lt;code&gt;search&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;d34u&quot;&gt;Формирует поисковый запрос&lt;/li&gt;
    &lt;li id=&quot;isyV&quot;&gt;Получает результаты&lt;/li&gt;
    &lt;li id=&quot;elcN&quot;&gt;Если нужно прочитать конкретную страницу — вызывает &lt;code&gt;fetch_content&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;eed8&quot;&gt;Анализирует полученную информацию&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;YbET&quot;&gt;Всё прозрачно: агенту не нужно объяснять, как искать — он делает это сам, когда понимает, что ему не хватает знаний.&lt;/p&gt;
  &lt;h2 id=&quot;особенности&quot;&gt;Особенности&lt;/h2&gt;
  &lt;ul id=&quot;gkDT&quot;&gt;
    &lt;li id=&quot;1uG7&quot;&gt;&lt;strong&gt;Без API-ключей&lt;/strong&gt; — DuckDuckGo не требует регистрации, всё бесплатно&lt;/li&gt;
    &lt;li id=&quot;lob3&quot;&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; — 30 запросов в минуту для поиска, 20 для загрузки контента&lt;/li&gt;
    &lt;li id=&quot;5maL&quot;&gt;&lt;strong&gt;SafeSearch&lt;/strong&gt; — настраиваемая фильтрация контента&lt;/li&gt;
    &lt;li id=&quot;RSGn&quot;&gt;&lt;strong&gt;Регионы&lt;/strong&gt; — можно локализовать поиск под нужную страну&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;итого&quot;&gt;Итого&lt;/h2&gt;
  &lt;p id=&quot;WDJ9&quot;&gt;DuckDuckGo Search эмсипи — простой способ дать оупенкод доступ к веб-поиску. Без регистраций, без API-ключей, без смс. Поставил за минуту — и агент сам ходит в интернет за актуальной информацией.&lt;/p&gt;

</content></entry><entry><id>beaverclan:deepwikimcp</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/deepwikimcp?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>DeepWiki MCP: AI-документация для любого репозитория</title><published>2026-06-28T07:10:27.054Z</published><updated>2026-06-28T07:10:27.054Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/fd/20/fd205c21-adac-4e53-839e-33f5bd4df623.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/deepwikimcp/logo.webp&quot;&gt;В работе с опенсорсом постоянно возникает ситуация: нашёл интересный репозиторий, а документация — это просто README. Хочется быстро разобраться, как всё устроено, но читать исходники в лоб — долго и лениво.</summary><content type="html">
  &lt;figure id=&quot;PR8p&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/deepwikimcp/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;зачем-это-нужно&quot;&gt;Зачем это нужно&lt;/h2&gt;
  &lt;p id=&quot;AKrG&quot;&gt;В работе с опенсорсом постоянно возникает ситуация: нашёл интересный репозиторий, а документация — это просто README. Хочется быстро разобраться, как всё устроено, но читать исходники в лоб — долго и лениво.&lt;/p&gt;
  &lt;p id=&quot;qS8S&quot;&gt;DeepWiki решает эту проблему: он анализирует код и README репозитория, и генерирует структурированную документацию с разделами, ссылками на исходники и с возможностью задавать вопросы.&lt;/p&gt;
  &lt;p id=&quot;sSVt&quot;&gt;А через MCP (Model Context Protocol) это становится доступно прямо из оупенкод — агент может сам сходить в диипвики за документацией по любому репозиторию.&lt;/p&gt;
  &lt;h2 id=&quot;что-такое-диипвики&quot;&gt;Что такое диипвики&lt;/h2&gt;
  &lt;p id=&quot;Cc7z&quot;&gt;&lt;a href=&quot;https://deepwiki.com/&quot; target=&quot;_blank&quot;&gt;DeepWiki&lt;/a&gt; — это AI-движок документации от Cognition Labs (те же ребята, что сделали Devin). Он берёт любой публичный GitHub-репозиторий, анализирует его код, README и файлы, и превращает всё это в удобную структурированную документацию.&lt;/p&gt;
  &lt;p id=&quot;V4yV&quot;&gt;Каждая страница документации содержит:&lt;/p&gt;
  &lt;ul id=&quot;JhYn&quot;&gt;
    &lt;li id=&quot;ABQV&quot;&gt;пояснения как работает тот или иной компонент&lt;/li&gt;
    &lt;li id=&quot;35sW&quot;&gt;ссылки на конкретные строки исходного кода (Sources)&lt;/li&gt;
    &lt;li id=&quot;uW6B&quot;&gt;навигацию по разделам&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;диипвики-в-браузере&quot;&gt;Диипвики в браузере&lt;/h2&gt;
  &lt;p id=&quot;STPg&quot;&gt;диипвики работает прямо в браузере. Просто замени &lt;code&gt;github.com&lt;/code&gt; на &lt;code&gt;deepwiki.com&lt;/code&gt; в URL любого публичного репозитория.&lt;/p&gt;
  &lt;p id=&quot;EN3H&quot;&gt;Вот так выглядит страница репозитория &lt;a href=&quot;https://deepwiki.com/LOWERTOP/Shadowrocket&quot; target=&quot;_blank&quot;&gt;LOWERTOP/Shadowrocket&lt;/a&gt; на диипвики:&lt;/p&gt;
  &lt;figure id=&quot;ZJ6K&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/deepwikimcp/2.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;G89L&quot;&gt;Слева — навигация по разделам: Proxy Management, Traffic Routing, Rules System, Configuration Files и т.д. Справа — контент с пояснениями и ссылками на исходники. Гораздо удобнее, чем читать README в GitHub.&lt;/p&gt;
  &lt;p id=&quot;xBJU&quot;&gt;Работает почти для любого публичного репозитория: &lt;code&gt;https://deepwiki.com/username/reponame&lt;/code&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;диипвики-эмсипи-для-оупенкод&quot;&gt;Диипвики эмсипи для оупенкод&lt;/h2&gt;
  &lt;p id=&quot;GwZf&quot;&gt;Cognition Labs предоставляют официальный эмсипи-сервер DeepWiki. Это удалённый сервер, поэтому не нужно ничего устанавливать локально — никаких Python, venv, uvx. Просто URL в конфиге.&lt;/p&gt;
  &lt;p id=&quot;rDts&quot;&gt;Добавляем в &lt;code&gt;~/.config/opencode/opencode.jsonc&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;ytSR&quot;&gt;{
  &amp;quot;$schema&amp;quot;: &amp;quot;https://opencode.ai/config.json&amp;quot;,
  &amp;quot;mcp&amp;quot;: {
    &amp;quot;deepwiki&amp;quot;: {
      &amp;quot;type&amp;quot;: &amp;quot;remote&amp;quot;,
      &amp;quot;url&amp;quot;: &amp;quot;https://mcp.deepwiki.com/mcp&amp;quot;
    }
  }
}
&lt;/pre&gt;
  &lt;p id=&quot;E90b&quot;&gt;Готово. Никаких зависимостей, никаких API-ключей — сервер бесплатный и не требует аутентификации.&lt;/p&gt;
  &lt;h2 id=&quot;инструменты&quot;&gt;Инструменты&lt;/h2&gt;
  &lt;p id=&quot;up03&quot;&gt;Сервер предоставляет три инструмента:&lt;/p&gt;
  &lt;h3 id=&quot;read_wiki_structurereponame&quot;&gt;read_wiki_structure(repoName)&lt;/h3&gt;
  &lt;p id=&quot;B9xo&quot;&gt;Возвращает структуру документации репозитория — список разделов и подразделов.&lt;/p&gt;
  &lt;h3 id=&quot;read_wiki_contentsreponame&quot;&gt;read_wiki_contents(repoName)&lt;/h3&gt;
  &lt;p id=&quot;UQ3Y&quot;&gt;Возвращает полное содержимое документации репозитория.&lt;/p&gt;
  &lt;h3 id=&quot;ask_questionreponame-question&quot;&gt;ask_question(repoName, question)&lt;/h3&gt;
  &lt;p id=&quot;kpb1&quot;&gt;Задать вопрос по коду репозитория. DeepWiki отвечает с привязкой к конкретным строкам исходников.&lt;/p&gt;
  &lt;h2 id=&quot;проверка&quot;&gt;Проверка&lt;/h2&gt;
  &lt;p id=&quot;vRO8&quot;&gt;Спрашиваю у оупенкод: “как устроена маршрутизация в ShadowRocket?”:&lt;/p&gt;
  &lt;figure id=&quot;jraj&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.ru/images/posts/deepwikimcp/1.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;6e9I&quot;&gt;Оупенкод вызывает &lt;code&gt;ask_question(&amp;quot;LOWERTOP/Shadowrocket&amp;quot;, &amp;quot;как устроена маршрутизация&amp;quot;)&lt;/code&gt;, диипвики анализирует код и возвращает структурированный ответ: глобальные режимы (Configuration/Proxy/Direct/Scene), система правил, типы правил. Каждый пункт привязан к исходному коду.&lt;/p&gt;
  &lt;h2 id=&quot;итого&quot;&gt;Итого&lt;/h2&gt;
  &lt;p id=&quot;7aEf&quot;&gt;DeepWiki эмсипи — это документация для почти любого репозитория прямо из оупенкод.&lt;/p&gt;
  &lt;p id=&quot;JEPE&quot;&gt;Вместе с &lt;a href=&quot;https://blog.tatarinovms.ru/posts/duckduckgosearchmcp/&quot; target=&quot;_blank&quot;&gt;DuckDuckGo Search эмсипи&lt;/a&gt; получается идеальная пара: DuckDuckGo ищет в интернете, DeepWiki объясняет код репозиториев. Оупенкод наконец-то видит и интернет, и документацию.&lt;/p&gt;

</content></entry><entry><id>beaverclan:blogontimewebs3</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/blogontimewebs3?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>Хостинг Hugo-блога на S3 Timeweb</title><published>2026-06-13T00:15:01.472Z</published><updated>2026-06-13T00:15:01.472Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/de/76/de76d744-9a6b-4441-8ca2-03b88d336bc6.png"></media:thumbnail><category term="blog" label="Blog"></category><summary type="html">&lt;img src=&quot;https://img4.teletype.in/files/f0/c6/f0c67423-5f38-43cf-bcf2-2c5a7e93c49d.png&quot;&gt;Долгое время мой блог жил на VDS — nginx, certbot, systemd-сервисы, бекапы, короче полноценный сервер. В какой-то момент стало лень следить за ещё одной машиной и особенно меня подтолкнули проблемы с разными хостингами и я решил переехать на статический S3-хостинг.</summary><content type="html">
  &lt;figure id=&quot;foTe&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f0/c6/f0c67423-5f38-43cf-bcf2-2c5a7e93c49d.png&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;kp5T&quot;&gt;Долгое время мой блог жил на VDS — nginx, certbot, systemd-сервисы, бекапы, короче полноценный сервер. В какой-то момент стало лень следить за ещё одной машиной и особенно меня подтолкнули проблемы с разными хостингами и я решил переехать на статический S3-хостинг.&lt;/p&gt;
  &lt;p id=&quot;f9Kc&quot;&gt;Пост про то — как я переехал, с какими граблями столкнулся и что в итоге получилось.&lt;/p&gt;
  &lt;h2 id=&quot;почему-timeweb-s3&quot;&gt;Почему Timeweb S3&lt;/h2&gt;
  &lt;p id=&quot;iZHc&quot;&gt;Почему именно Timeweb, а не Яндекс Облако или Selectel? Тут всё просто: у меня уже были там аккаунты, а S3 у них стоит копейки. Для статики — идеально.&lt;/p&gt;
  &lt;p id=&quot;fKiz&quot;&gt;Из коробки Timeweb S3 умеет раздавать статический сайт, выдаёт URL вида &lt;code&gt;*.website.twcstorage.ru&lt;/code&gt;, поддерживает кастомные заголовки и политики.&lt;/p&gt;
  &lt;h2 id=&quot;что-нужно&quot;&gt;Что нужно&lt;/h2&gt;
  &lt;ul id=&quot;qJS4&quot;&gt;
    &lt;li id=&quot;7FQr&quot;&gt;Аккаунт в Timeweb (уже был)&lt;/li&gt;
    &lt;li id=&quot;MEAR&quot;&gt;Hugo&lt;/li&gt;
    &lt;li id=&quot;fRuO&quot;&gt;Репозиторий блога на GitHub (уже был)&lt;/li&gt;
    &lt;li id=&quot;WjTf&quot;&gt;Домен (уже был)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;шаг-1-создание-бакета&quot;&gt;Шаг 1: Создание бакета&lt;/h2&gt;
  &lt;ol id=&quot;4pHe&quot;&gt;
    &lt;li id=&quot;MN1U&quot;&gt;Заходим в панель Timeweb → S3 → Создать бакет&lt;/li&gt;
    &lt;li id=&quot;LL1P&quot;&gt;Выбираем регион, имя бакета&lt;/li&gt;
    &lt;li id=&quot;Mqk0&quot;&gt;После создания открываем бакет → Настройки → Хостинг статического сайта → Включаем&lt;/li&gt;
    &lt;li id=&quot;3ZPg&quot;&gt;Получаем URL: &lt;code&gt;https://&amp;lt;id&amp;gt;.website.twcstorage.ru&lt;/code&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h2 id=&quot;шаг-2-s3-ключи&quot;&gt;Шаг 2: S3-ключи&lt;/h2&gt;
  &lt;p id=&quot;ImNG&quot;&gt;В панели Timeweb идём в сервисные аккаунты → создаём ключ с доступом к бакету (на запись и чтение). Нам понадобятся:&lt;/p&gt;
  &lt;ul id=&quot;zcdA&quot;&gt;
    &lt;li id=&quot;VP5n&quot;&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;MK2D&quot;&gt;&lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;snl7&quot;&gt;&lt;code&gt;AWS_ENDPOINT_URL&lt;/code&gt; — &lt;code&gt;https://s3.twcstorage.ru&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;PKhx&quot;&gt;И имя бакета&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;шаг-3-github-actions&quot;&gt;Шаг 3: GitHub Actions&lt;/h2&gt;
  &lt;p id=&quot;lfMF&quot;&gt;Деплой настроил через GitHub Actions. Workflow выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;9uie&quot;&gt;name: Deploy blog to S3

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: peaceiris/actions-hugo@v3
        with:
          extended: true

      - run: hugo --gc

      - uses: jakejarvis/s3-sync-action@master
        with:
          args: --delete
        env:
          AWS_S3_BUCKET: ${{ secrets.AWS_BUCKET_NAME }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_ENDPOINT_URL: ${{ secrets.AWS_ENDPOINT_URL }}
&lt;/pre&gt;
  &lt;p id=&quot;HyxA&quot;&gt;Секреты (&lt;code&gt;AWS_*&lt;/code&gt;) храню в настройках репозитория GitHub — Settings → Secrets and variables → Actions.&lt;/p&gt;
  &lt;h2 id=&quot;шаг-4-деплой&quot;&gt;Шаг 4: Деплой&lt;/h2&gt;
  &lt;p id=&quot;fh1C&quot;&gt;Пушим в main:&lt;/p&gt;
  &lt;pre id=&quot;1vJW&quot;&gt;git push origin main
&lt;/pre&gt;
  &lt;p id=&quot;aGH9&quot;&gt;GitHub Actions собирает сайт и синхронизирует с бакетом. Всё, сайт на S3, никаких ssh и ручных заливок.&lt;/p&gt;
  &lt;h2 id=&quot;шаг-5-домены-не-так-всё-просто&quot;&gt;Шаг 5: Домены (не так всё просто)&lt;/h2&gt;
  &lt;p id=&quot;g7dg&quot;&gt;Настраиваем CNAME в DNS:&lt;/p&gt;
  &lt;pre id=&quot;AAlh&quot;&gt;blog.tatarinovms.ru → s3.twcstorage.ru
blog.tatarinovms.space → s3.twcstorage.ru
&lt;/pre&gt;
  &lt;p id=&quot;N0ZI&quot;&gt;Ждём, пока DNS обновится, открываем браузер… и получаем &lt;code&gt;AccessDenied&lt;/code&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;подводный-камень-кастомные-домены-не-работают&quot;&gt;Подводный камень: кастомные домены не работают&lt;/h3&gt;
  &lt;p id=&quot;B8Uu&quot;&gt;Как оказалось, Timeweb S3 &lt;a href=&quot;https://timeweb.cloud/docs/s3-storage/supported-features/static-websites#ogranicheniya&quot; target=&quot;_blank&quot;&gt;не поддерживает кастомные домены&lt;/a&gt;. Вообще. Только их &lt;code&gt;*.website.twcstorage.ru&lt;/code&gt;. На момент написания поста ответ поддержки это подтвердил.&lt;/p&gt;
  &lt;p id=&quot;YhcL&quot;&gt;Есть два пути:&lt;/p&gt;
  &lt;p id=&quot;1Bix&quot;&gt;&lt;strong&gt;Вариант 1: CloudFlare&lt;/strong&gt; Меняем NS на CloudFlare, он проксирует запросы на S3-эндпоинт и выдаёт свой SSL. VDS не нужен. Бесплатно. Но мы знаем как в некоторых регионах работает CloudFlare, скажем мягко - с перебоями.&lt;/p&gt;
  &lt;p id=&quot;FMwK&quot;&gt;&lt;strong&gt;Вариант 2: nginx reverse proxy&lt;/strong&gt; Пришла простая идея, так как есть в загашнике VDS, то мы ставим nginx на VDS, он проксирует кастомные домены на S3 URL. SSL через certbot. VDS всё равно есть под другие задачи. Конфиг nginx:&lt;/p&gt;
  &lt;pre id=&quot;WmqL&quot;&gt;server {
    listen 80 default_server;
    server_name blog.tatarinovms.ru blog.tatarinovms.space;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name blog.tatarinovms.ru blog.tatarinovms.space;

    ssl_certificate /etc/letsencrypt/live/blog.tatarinovms.space/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.tatarinovms.space/privkey.pem;

    location / {
        proxy_pass https://id.website.twcstorage.ru;
        proxy_ssl_verify off;
        proxy_ssl_server_name on;
        proxy_set_header Host id.website.twcstorage.ru;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
&lt;/pre&gt;
  &lt;p id=&quot;FouX&quot;&gt;SSL получил через certbot:&lt;/p&gt;
  &lt;pre id=&quot;6kJP&quot;&gt;certbot --nginx -d blog.tatarinovms.ru -d blog.tatarinovms.space
&lt;/pre&gt;
  &lt;h2 id=&quot;итоговая-схема&quot;&gt;Итоговая схема&lt;/h2&gt;
  &lt;pre id=&quot;NmyK&quot;&gt;Пуш в main → GitHub Actions → Hugo build → aws s3 sync → S3 бакет → DNS: blog.tatarinovms.ru / blog.tatarinovms.space → A → VDS → nginx reverse proxy → S3 (*.website.twcstorage.ru)
&lt;/pre&gt;
  &lt;p id=&quot;8g5B&quot;&gt;При пуше в main GitHub Actions сам собирает Hugo и синхронизирует с S3 — nginx просто проксирует то, что уже лежит в бакете. Редеплой занимает меньше минуты.&lt;/p&gt;
  &lt;p id=&quot;jUw3&quot;&gt;Timeweb S3 как хостинг статики — отличное решение. Но с кастомными доменами придётся извернуться. Надеюсь, когда-нибудь они добавят эту возможность, но пока — nginx.&lt;/p&gt;

</content></entry><entry><id>beaverclan:finetune</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/finetune?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>FineTune — бесплатный аудио-микшер для macOS</title><published>2026-05-28T16:03:17.976Z</published><updated>2026-05-28T16:03:17.976Z</updated><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/finetune/logo.webp&quot;&gt;FineTune — это бесплатная open-source утилита для macOS, которая живёт в меню-баре и даёт полный контроль над аудио на системном уровне. Регулировка громкости каждого приложения независимо, маршрутизация звука на разные устройства, 10-полосный эквалайзер и коррекция АЧХ для наушников — всё в одном окне.</summary><content type="html">
  &lt;figure id=&quot;x4gH&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/finetune/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;что-такое-finetune&quot;&gt;Что такое FineTune?&lt;/h2&gt;
  &lt;p id=&quot;HB1K&quot;&gt;FineTune — это бесплатная open-source утилита для macOS, которая живёт в меню-баре и даёт полный контроль над аудио на системном уровне. Регулировка громкости каждого приложения независимо, маршрутизация звука на разные устройства, 10-полосный эквалайзер и коррекция АЧХ для наушников — всё в одном окне.&lt;/p&gt;
  &lt;p id=&quot;9piW&quot;&gt;Для перехвата аудиопотоков FineTune создаёт виртуальное аудиоустройство. Оно появляется в системных настройках звука и работает как прослойка между приложениями и вашими колонками/наушниками.&lt;/p&gt;
  &lt;p id=&quot;c6RU&quot;&gt;Написан на SwiftUI, требует macOS 15.0+.&lt;/p&gt;
  &lt;h2 id=&quot;основные-возможности&quot;&gt;Основные возможности&lt;/h2&gt;
  &lt;h3 id=&quot;управление-громкостью&quot;&gt;Управление громкостью&lt;/h3&gt;
  &lt;ul id=&quot;XUet&quot;&gt;
    &lt;li id=&quot;mqq7&quot;&gt;&lt;strong&gt;Per-app громкость&lt;/strong&gt; — отдельный слайдер и mute для каждого приложения&lt;/li&gt;
    &lt;li id=&quot;f3op&quot;&gt;&lt;strong&gt;Pinned apps&lt;/strong&gt; — закрепить приложение в меню-баре, даже когда оно не воспроизводит звук (удобно настроить EQ и маршрутизацию заранее)&lt;/li&gt;
    &lt;li id=&quot;Ubss&quot;&gt;&lt;strong&gt;Ignore apps&lt;/strong&gt; — полностью исключить приложение из управления FineTune&lt;/li&gt;
    &lt;li id=&quot;VzXt&quot;&gt;&lt;strong&gt;Scroll-wheel&lt;/strong&gt; — наведите курсор на любой слайдер и крутите колёсико&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;горячие-клавиши&quot;&gt;Горячие клавиши&lt;/h3&gt;
  &lt;ul id=&quot;UFfO&quot;&gt;
    &lt;li id=&quot;LXwg&quot;&gt;&lt;strong&gt;Глобальные хоткеи&lt;/strong&gt; — назначьте свои комбинации на App Volume Up/Down и Mute. Работают даже когда приложение свёрнуто&lt;/li&gt;
    &lt;li id=&quot;3DdG&quot;&gt;&lt;strong&gt;Toggle Popup&lt;/strong&gt; — повесьте хоткей на открытие/закрытие окна FineTune, работает из полноэкранных приложений&lt;/li&gt;
    &lt;li id=&quot;G9CD&quot;&gt;&lt;strong&gt;Навигация внутри попапа&lt;/strong&gt; — стрелки &lt;code&gt;↑↓&lt;/code&gt; между строками, &lt;code&gt;←→&lt;/code&gt; регулировка громкости, &lt;code&gt;M&lt;/code&gt;mute, &lt;code&gt;Return/Space&lt;/code&gt; активация, &lt;code&gt;Tab&lt;/code&gt; переключение вкладок устройств&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;маршрутизация&quot;&gt;Маршрутизация&lt;/h3&gt;
  &lt;ul id=&quot;ulU3&quot;&gt;
    &lt;li id=&quot;4T2Q&quot;&gt;&lt;strong&gt;Multi-device output&lt;/strong&gt; — вывод звука на несколько устройств одновременно&lt;/li&gt;
    &lt;li id=&quot;MqmG&quot;&gt;&lt;strong&gt;Audio routing&lt;/strong&gt; — отправлять разные приложения на разные устройства&lt;/li&gt;
    &lt;li id=&quot;5tvL&quot;&gt;&lt;strong&gt;Device priority&lt;/strong&gt; — автопереключение при подключении нового устройства&lt;/li&gt;
    &lt;li id=&quot;hetq&quot;&gt;&lt;strong&gt;Auto-restore&lt;/strong&gt; — при переподключении устройства настройки (громкость, маршрут, EQ) восстанавливаются автоматически&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;эквалайзер&quot;&gt;Эквалайзер&lt;/h3&gt;
  &lt;ul id=&quot;XRNY&quot;&gt;
    &lt;li id=&quot;8x5C&quot;&gt;&lt;strong&gt;10 полос&lt;/strong&gt;, 20 готовых пресетов&lt;/li&gt;
    &lt;li id=&quot;ppow&quot;&gt;&lt;strong&gt;Пользовательские пресеты&lt;/strong&gt; — сохраняйте свои настройки и применяйте к разным приложениям&lt;/li&gt;
    &lt;li id=&quot;Cwzm&quot;&gt;&lt;strong&gt;AutoEQ headphone correction&lt;/strong&gt; — коррекция АЧХ под конкретную модель наушников из базы AutoEQ (тысячи профилей). Можно импортировать свои ParametricEQ.txt&lt;/li&gt;
    &lt;li id=&quot;b1f4&quot;&gt;&lt;strong&gt;Загрузка пресета&lt;/strong&gt; — выбрав пресет для своих наушников, FineTune запоминает его и применяет автоматически при каждом подключении этой модели&lt;/li&gt;
    &lt;li id=&quot;eutN&quot;&gt;&lt;strong&gt;Loudness compensation&lt;/strong&gt; — автоматическая коррекция низких и высоких частот на малой громкости по стандарту ISO 226:2023&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;системное&quot;&gt;Системное&lt;/h3&gt;
  &lt;ul id=&quot;YOCS&quot;&gt;
    &lt;li id=&quot;qoSj&quot;&gt;&lt;strong&gt;Input device control&lt;/strong&gt; — уровень микрофона&lt;/li&gt;
    &lt;li id=&quot;HUp6&quot;&gt;&lt;strong&gt;Alert volume&lt;/strong&gt; — громкость системных уведомлений&lt;/li&gt;
    &lt;li id=&quot;Aiuu&quot;&gt;&lt;strong&gt;DDC&lt;/strong&gt; — регулировка громкости внешних мониторов&lt;/li&gt;
    &lt;li id=&quot;yjVx&quot;&gt;&lt;strong&gt;Volume HUD&lt;/strong&gt; — встроенный индикатор громкости (Tahoe или Classic стиль)&lt;/li&gt;
    &lt;li id=&quot;Qj8J&quot;&gt;&lt;strong&gt;Медиа-клавиши F10-F12&lt;/strong&gt; — работают даже на USB DAC и HDMI, где штатные клавиши macOS бесполезны&lt;/li&gt;
    &lt;li id=&quot;mly5&quot;&gt;&lt;strong&gt;Bluetooth&lt;/strong&gt; — подключение устройств прямо из меню-бара&lt;/li&gt;
    &lt;li id=&quot;mUyX&quot;&gt;&lt;strong&gt;URL schemes&lt;/strong&gt; — автоматизация через shell, Shortcuts или Raycast’о подобное&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;установка&quot;&gt;Установка&lt;/h2&gt;
  &lt;pre id=&quot;kHTU&quot;&gt;brew install --cask finetune
&lt;/pre&gt;
  &lt;p id=&quot;9llU&quot;&gt;Или скачайте DMG с &lt;a href=&quot;https://github.com/ronitsingh10/FineTune/releases/latest&quot; target=&quot;_blank&quot;&gt;GitHub Releases&lt;/a&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;быстрый-старт&quot;&gt;Быстрый старт&lt;/h2&gt;
  &lt;ol id=&quot;CW8s&quot;&gt;
    &lt;li id=&quot;5mkA&quot;&gt;Запустите FineTune из папки Applications&lt;/li&gt;
    &lt;li id=&quot;82RN&quot;&gt;Разрешите &lt;strong&gt;Screen &amp;amp; System Audio Recording&lt;/strong&gt; — это необходимо для перехвата аудиопотоков&lt;/li&gt;
    &lt;li id=&quot;PTmo&quot;&gt;Нажмите на иконку FineTune в меню-баре — приложения, воспроизводящие звук, появятся автоматически&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;BoLb&quot;&gt;Готово. Регулируйте громкость, маршрутизируйте звук, настраивайте EQ.&lt;/p&gt;
  &lt;h2 id=&quot;полезные-фышки&quot;&gt;Полезные фЫшки&lt;/h2&gt;
  &lt;ul id=&quot;BauV&quot;&gt;
    &lt;li id=&quot;swJr&quot;&gt;&lt;strong&gt;Автопереключение на Bluetooth-гарнитуру&lt;/strong&gt;: откройте edit mode (карандаш) и перетащите устройство выше встроенных динамиков — FineTune будет переключаться на него при подключении&lt;/li&gt;
    &lt;li id=&quot;8F7i&quot;&gt;&lt;strong&gt;Управление с клавиатуры&lt;/strong&gt;: откройте попап и пользуйтесь стрелками.&lt;/li&gt;
    &lt;li id=&quot;SHMR&quot;&gt;&lt;strong&gt;URL schemes&lt;/strong&gt; — automate volume, mute, device routing, and more from scriptsFineTune понимает URL-команды формата &lt;code&gt;finetune://&lt;/code&gt;.&lt;code&gt;finetune://set-volumes?app=com.spotify.client&amp;amp;volume=50 finetune://set-mute?app=com.spotify.client&amp;amp;muted=true finetune://toggle-mute?app=com.hnc.Discord finetune://set-device?app=com.apple.Music&amp;amp;device=DEVICE_UID finetune://reset &lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;x9TA&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/finetune/1.webp&quot; width=&quot;500&quot; /&gt;
  &lt;/figure&gt;

</content></entry><entry><id>beaverclan:qwen3asronmacos</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/qwen3asronmacos?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>Qwen3 ASR на macOS</title><published>2026-05-03T11:51:17.499Z</published><updated>2026-05-03T11:51:17.499Z</updated><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/qwen3asronmacos/logo.webp&quot;&gt;В этом гайде я покажу, как развернуть и запустить модель распознавания речи Qwen3‑ASR через пакет mlx-qwen3-asr на macOS с M-чипом. Решение позволяет транскрибировать аудио из видеофайлов с поддержкой русского языка и сохранять результат в разных форматах: SRT, VTT, TXT, JSON.</summary><content type="html">
  &lt;figure id=&quot;qDLy&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/qwen3asronmacos/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;H5S1&quot;&gt;В этом гайде я покажу, как развернуть и запустить модель распознавания речи Qwen3‑ASR через пакет mlx-qwen3-asr на macOS с M-чипом. Решение позволяет транскрибировать аудио из видеофайлов с поддержкой русского языка и сохранять результат в разных форматах: SRT, VTT, TXT, JSON.&lt;/p&gt;
  &lt;h1 id=&quot;что-такое-mlx-qwen3-asr&quot;&gt;Что такое mlx-qwen3-asr?&lt;/h1&gt;
  &lt;p id=&quot;DpqW&quot;&gt;&lt;a href=&quot;https://github.com/moona3k/mlx-qwen3-asr&quot; target=&quot;_blank&quot;&gt;mlx-qwen3-asr&lt;/a&gt; - это Python‑пакет, предоставляющий удобный интерфейс к модели Qwen3‑ASR‑1.7B от Alibaba Cloud, оптимизированной для работы на чипах Apple Silicon через фреймворк MLX. Модель поддерживает несколько языков, включая наш родной русский, и позволяет получать транскрипцию с тайм‑кодами.&lt;/p&gt;
  &lt;h2 id=&quot;требования&quot;&gt;Требования&lt;/h2&gt;
  &lt;ul id=&quot;brvV&quot;&gt;
    &lt;li id=&quot;Bjzn&quot;&gt;macOS&lt;/li&gt;
    &lt;li id=&quot;aSjr&quot;&gt;Установленный Python 3.11&lt;/li&gt;
    &lt;li id=&quot;aImQ&quot;&gt;Руки&lt;/li&gt;
    &lt;li id=&quot;syvz&quot;&gt;Свободное место на диске (модель ~3 ГБ)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h1 id=&quot;установка-и-настройка&quot;&gt;Установка и настройка&lt;/h1&gt;
  &lt;h2 id=&quot;подготовка-директории-проекта&quot;&gt;Подготовка директории проекта&lt;/h2&gt;
  &lt;p id=&quot;P4NZ&quot;&gt;Создайте отдельную папку для проекта и перейдите в неё, у меня будет так:&lt;/p&gt;
  &lt;pre id=&quot;PQaw&quot;&gt;mkdir -p ~/Documents/ai/asr
cd ~/Documents/ai/asr
&lt;/pre&gt;
  &lt;h2 id=&quot;создание-виртуального-окружения&quot;&gt;Создание виртуального окружения&lt;/h2&gt;
  &lt;pre id=&quot;QSXM&quot;&gt;python3.11 -m venv venv
&lt;/pre&gt;
  &lt;h2 id=&quot;активация-окружения&quot;&gt;Активация окружения&lt;/h2&gt;
  &lt;p id=&quot;wtYF&quot;&gt;Активируйте виртуальное окружение:&lt;/p&gt;
  &lt;pre id=&quot;Yv0b&quot;&gt;source venv/bin/activate
&lt;/pre&gt;
  &lt;h2 id=&quot;обновление-pip-и-установка-пакета&quot;&gt;Обновление pip и установка пакета&lt;/h2&gt;
  &lt;p id=&quot;jKp5&quot;&gt;Обновите менеджер пакетов и установите mlx-qwen3-asr:&lt;/p&gt;
  &lt;pre id=&quot;ex17&quot;&gt;pip install --upgrade pip
pip install mlx-qwen3-asr
&lt;/pre&gt;
  &lt;p id=&quot;Qrot&quot;&gt;Установка может занять несколько минут — загружаются зависимости и модель.&lt;/p&gt;
  &lt;h2 id=&quot;создание-скрипта-автоматизации&quot;&gt;Создание скрипта автоматизации&lt;/h2&gt;
  &lt;p id=&quot;QI99&quot;&gt;Чтобы не вводить команды вручную каждый раз, создадим shell‑скрипт с небольшим интерактивным интерфейсом.&lt;/p&gt;
  &lt;h3 id=&quot;создайте-файл-скрипта&quot;&gt;Создайте файл скрипта&lt;/h3&gt;
  &lt;ul id=&quot;m9UL&quot;&gt;
    &lt;li id=&quot;KfxS&quot;&gt;Создадим скрипт в любимом текстовом редакторе:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;76SI&quot;&gt;vim asr_process.sh
&lt;/pre&gt;
  &lt;ul id=&quot;uQps&quot;&gt;
    &lt;li id=&quot;RADG&quot;&gt;Вставьте этот &lt;a href=&quot;https://blog.tatarinovms.space/static/scripts/qwen3asronmacos/asr_process.sh&quot; target=&quot;_blank&quot;&gt;код&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;FFX8&quot;&gt;Укажите настройку &lt;code&gt;VENV_BIN=&lt;/code&gt;, где будет путь к созданной вами папке.&lt;/li&gt;
    &lt;li id=&quot;9JJi&quot;&gt;Сохраняем файл&lt;/li&gt;
    &lt;li id=&quot;hzFO&quot;&gt;Делаем скрипт исполняемым&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;dNfd&quot;&gt;chmod +x asr_process.sh
&lt;/pre&gt;
  &lt;h2 id=&quot;отправляем-файл-на-распознавание&quot;&gt;Отправляем файл на распознавание&lt;/h2&gt;
  &lt;ul id=&quot;zhFw&quot;&gt;
    &lt;li id=&quot;hDj1&quot;&gt;Запускаем скрипт&lt;/li&gt;
  &lt;/ul&gt;
  &lt;pre id=&quot;Pxyg&quot;&gt;./asr_process.sh
&lt;/pre&gt;
  &lt;ul id=&quot;SogN&quot;&gt;
    &lt;li id=&quot;UtVV&quot;&gt;откроет диалоговое окно для выбора файла&lt;/li&gt;
    &lt;li id=&quot;DBQx&quot;&gt;потом скрипт предложит выбрать формат вывода&lt;/li&gt;
    &lt;li id=&quot;dS5f&quot;&gt;позволит указать папку для сохранения&lt;/li&gt;
    &lt;li id=&quot;J5mK&quot;&gt;запустится распознавание и покажет прогресс (при первом запуске модель скачается)&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>beaverclan:voxcpm</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/voxcpm?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>VoxCPM - на ноуте. Клонируем свой голос</title><published>2026-04-26T17:26:16.498Z</published><updated>2026-04-26T17:26:16.498Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/35/72/35721e82-9c8b-4e50-926b-70083be2ca65.png"></media:thumbnail><category term="blog" label="Blog"></category><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/voxcpm/logo.webp&quot;&gt;Данное руководство содержит пошаговые инструкции по установке и запуску VoxCPM на macOS с процессорами Apple Silicon. Игрался на своем ноуте.</summary><content type="html">
  &lt;figure id=&quot;Id5N&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/voxcpm/logo.webp&quot; width=&quot;800&quot; /&gt;
  &lt;/figure&gt;
  &lt;h1 id=&quot;развёртывание-voxcpm-на-macbook-с-чипом-apple-silicon&quot;&gt;Развёртывание VoxCPM на MacBook с чипом Apple Silicon&lt;/h1&gt;
  &lt;p id=&quot;Gh74&quot;&gt;Данное руководство содержит пошаговые инструкции по установке и запуску &lt;a href=&quot;https://github.com/OpenBMB/VoxCPM&quot; target=&quot;_blank&quot;&gt;VoxCPM&lt;/a&gt; на macOS с процессорами Apple Silicon. Игрался на своем ноуте.&lt;/p&gt;
  &lt;h2 id=&quot;скачиваем-репозиторий-проекта&quot;&gt;Скачиваем репозиторий проекта&lt;/h2&gt;
  &lt;p id=&quot;snAR&quot;&gt;Переходим в папку, где у вас всё будет аккуратно лежать и скачиваем репу:&lt;/p&gt;
  &lt;pre id=&quot;6Xat&quot;&gt;git clone https://github.com/OpenBMB/VoxCPM.git
cd VoxCPM
&lt;/pre&gt;
  &lt;h2 id=&quot;настройка-доступа-к-hugging-face&quot;&gt;Настройка доступа к Hugging Face&lt;/h2&gt;
  &lt;p id=&quot;C49j&quot;&gt;Для ускорения загрузки моделей и повышения лимитов запросов рекомендуется настроить токен доступа на Hugging Face&lt;/p&gt;
  &lt;h3 id=&quot;получение-токена&quot;&gt;Получение токена&lt;/h3&gt;
  &lt;ol id=&quot;TSEf&quot;&gt;
    &lt;li id=&quot;Mod9&quot;&gt;Перейдите на &lt;a href=&quot;https://huggingface.co/settings/tokens&quot; target=&quot;_blank&quot;&gt;https://huggingface.co/settings/tokens&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;WUoP&quot;&gt;Создайте новый токен с правами &lt;strong&gt;Read&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;LtUN&quot;&gt;Скопируйте токен (формат: &lt;code&gt;hf_...&lt;/code&gt;)&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;настройка-токена&quot;&gt;Настройка токена&lt;/h3&gt;
  &lt;p id=&quot;ZO7z&quot;&gt;&lt;strong&gt;Способ 1: Через huggingface-cli&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;mmYn&quot;&gt;pip install -U huggingface_hub
hf auth login
# Вставьте токен при запросе
&lt;/pre&gt;
  &lt;p id=&quot;3ooi&quot;&gt;&lt;strong&gt;Способ 2: Через переменную окружения&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;tu4Z&quot;&gt;# Временно для сессии
export HF_TOKEN=&amp;quot;hf_ваш_токен_здесь&amp;quot;

# Или навсегда (добавить в ~/.zshrc)
echo &amp;#x27;export HF_TOKEN=&amp;quot;hf_ваш_токен_здесь&amp;quot;&amp;#x27; &amp;gt;&amp;gt; ~/.zshrc
source ~/.zshrc
&lt;/pre&gt;
  &lt;h2 id=&quot;установка-python-310-через-pyenv&quot;&gt;Установка Python 3.10+ через pyenv&lt;/h2&gt;
  &lt;h3 id=&quot;установка-homebrew-если-не-установлен-но-навряд-ли-конечно&quot;&gt;Установка Homebrew (если не установлен, но навряд ли, конечно)&lt;/h3&gt;
  &lt;pre id=&quot;2Xt7&quot;&gt;/bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;
&lt;/pre&gt;
  &lt;h3 id=&quot;установка-pyenv-и-зависимостей&quot;&gt;Установка pyenv и зависимостей&lt;/h3&gt;
  &lt;pre id=&quot;9gRa&quot;&gt;brew install pyenv openssl readline sqlite3 xz zlib pkgconf autoconf
&lt;/pre&gt;
  &lt;h3 id=&quot;настройка-окружения-оболочки&quot;&gt;Настройка окружения оболочки&lt;/h3&gt;
  &lt;p id=&quot;8IBO&quot;&gt;Добавьте следующие строки в &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;nQdC&quot;&gt;export PYENV_ROOT=&amp;quot;$HOME/.pyenv&amp;quot;
export PATH=&amp;quot;$PYENV_ROOT/bin:$PATH&amp;quot;
eval &amp;quot;$(pyenv init --path)&amp;quot;
eval &amp;quot;$(pyenv init -)&amp;quot;
&lt;/pre&gt;
  &lt;p id=&quot;KWgk&quot;&gt;Примените изменения:&lt;/p&gt;
  &lt;pre id=&quot;Kr3r&quot;&gt;source ~/.zshrc
&lt;/pre&gt;
  &lt;h3 id=&quot;установка-python-31014&quot;&gt;Установка Python 3.10.14&lt;/h3&gt;
  &lt;pre id=&quot;eZcN&quot;&gt;pyenv install 3.10.14
&lt;/pre&gt;
  &lt;h3 id=&quot;настройка-версии-для-проекта&quot;&gt;Настройка версии для проекта&lt;/h3&gt;
  &lt;p id=&quot;U8EM&quot;&gt;Перейдите в папку проекта, которую мы скачали ранее и указываем локальную версию Python:&lt;/p&gt;
  &lt;pre id=&quot;T3Rc&quot;&gt;cd ~/Documents/ai/VoxCPM 
pyenv local 3.10.14
python --version  # Должно вывести: Python 3.10.14
&lt;/pre&gt;
  &lt;h2 id=&quot;настройка-проекта-и-установка-зависимостей&quot;&gt;Настройка проекта и установка зависимостей&lt;/h2&gt;
  &lt;h3 id=&quot;создание-виртуального-окружения&quot;&gt;Создание виртуального окружения&lt;/h3&gt;
  &lt;pre id=&quot;fHZ0&quot;&gt;# В папке проекта
python -m venv venv
source venv/bin/activate
pip install --upgrade pip
&lt;/pre&gt;
  &lt;h3 id=&quot;установка-проекта-в-режиме-разработки&quot;&gt;Установка проекта в режиме разработки&lt;/h3&gt;
  &lt;pre id=&quot;6BbR&quot;&gt;pip install -e .
&lt;/pre&gt;
  &lt;h3 id=&quot;проверка-установки&quot;&gt;Проверка установки&lt;/h3&gt;
  &lt;pre id=&quot;KE1d&quot;&gt;which voxcpm
# Должно указывать на путь внутри venv

voxcpm --help
# Должно отобразить справку по командам и доступным флагам
&lt;/pre&gt;
  &lt;h3 id=&quot;скачиваем-модель-в-папку&quot;&gt;Скачиваем модель в папку&lt;/h3&gt;
  &lt;p id=&quot;V0TC&quot;&gt;Делаем папку для модели и качаем модель:&lt;/p&gt;
  &lt;pre id=&quot;Ptl3&quot;&gt;mkdir -p models/VoxCPM-2B
hf download openbmb/VoxCPM2 --local-dir ./models/VoxCPM2
&lt;/pre&gt;
  &lt;h2 id=&quot;использование-через-cli&quot;&gt;Использование через CLI&lt;/h2&gt;
  &lt;h3 id=&quot;базовый-синтаксис&quot;&gt;Базовый синтаксис&lt;/h3&gt;
  &lt;p id=&quot;jQ7M&quot;&gt;В без все просто:&lt;/p&gt;
  &lt;pre id=&quot;CvTx&quot;&gt;voxcpm &amp;lt;режим&amp;gt; [параметры]
&lt;/pre&gt;
  &lt;p id=&quot;TQmi&quot;&gt;Но мы пойдём путём клонирования своего голоса для озвучки текста.&lt;/p&gt;
  &lt;h3 id=&quot;готовим-файл-для-клонирования&quot;&gt;Готовим файл для клонирования&lt;/h3&gt;
  &lt;p id=&quot;DrjQ&quot;&gt;Я просто записал аудиосообщение в одном голубом мессенджере, сохранил его и перекодировал через ffmpeg в wav. Текст сообщения был такой: Это образец моего голоса. Я говорю здесь целых пять секунд.&lt;/p&gt;
  &lt;p id=&quot;HGR6&quot;&gt;Файл с текстом и аудио сохранил в папке ./ref. Т. е. ref.txt и ref.wav&lt;/p&gt;
  &lt;h3 id=&quot;готовим-текст-для-озвучки&quot;&gt;Готовим текст для озвучки&lt;/h3&gt;
  &lt;p id=&quot;byzC&quot;&gt;Создам папку output и inpit чтобы папку не замусоривать. Создаю текст для озвучки:&lt;/p&gt;
  &lt;pre id=&quot;vV2y&quot;&gt;vim ./inpit/anime.txt
&lt;/pre&gt;
  &lt;p id=&quot;bXiU&quot;&gt;Накидал туда описание аниме - &lt;a href=&quot;https://hd.kinopoisk.ru/film/b04631f828704a91b2c4730cf1c32699&quot; target=&quot;_blank&quot;&gt;Ателье колдовских колпаков&lt;/a&gt;&lt;/p&gt;
  &lt;h3 id=&quot;запускаем-озвучку-с-клонированием-нашего-голоса&quot;&gt;Запускаем озвучку с клонированием нашего голоса&lt;/h3&gt;
  &lt;p id=&quot;k30l&quot;&gt;Запускаем озвучку нашего текста с клонированием голоса в папку output:&lt;/p&gt;
  &lt;pre id=&quot;IcdW&quot;&gt;voxcpm clone --text &amp;quot;$(cat ./inpit/anime.txt)&amp;quot; --prompt-audio ./ref/ref.wav --prompt-text &amp;quot;$(cat ./ref/ref.txt)&amp;quot; --reference-audio ./ref/ref.wav --output ./output/anime_18.wav --model-path ./models/VoxCPM2 --device mps --no-optimize --cfg-value 1.8 --inference-timesteps 20 --normalize --no-denoiser
&lt;/pre&gt;
  &lt;h3 id=&quot;что-у-нас-по-параметрам&quot;&gt;Что у нас по параметрам?&lt;/h3&gt;
  &lt;p id=&quot;Pkth&quot;&gt;Параметр&lt;/p&gt;
  &lt;p id=&quot;lKG2&quot;&gt;Значение в команде&lt;/p&gt;
  &lt;p id=&quot;2fJZ&quot;&gt;Назначение&lt;/p&gt;
  &lt;p id=&quot;cZQq&quot;&gt;&lt;code&gt;voxcpm clone&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;fXwd&quot;&gt;&lt;code&gt;clone&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;i9Fc&quot;&gt;Активация режима клонирования голоса&lt;/p&gt;
  &lt;p id=&quot;o0gO&quot;&gt;&lt;code&gt;--text&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;yx27&quot;&gt;&lt;code&gt;&amp;quot;$(cat ./inpit/anime.txt)&amp;quot;&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;3vRL&quot;&gt;Целевой текст для генерации&lt;/p&gt;
  &lt;p id=&quot;MVHt&quot;&gt;&lt;code&gt;--prompt-audio&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;cF0I&quot;&gt;&lt;code&gt;./ref/ref.wav&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;t0Z6&quot;&gt;Аудио-референс&lt;/p&gt;
  &lt;p id=&quot;hCLk&quot;&gt;&lt;code&gt;--prompt-text&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;uHDf&quot;&gt;&lt;code&gt;&amp;quot;$(cat ./ref/ref.txt)&amp;quot;&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;8qsw&quot;&gt;Точная транскрипция &lt;code&gt;prompt-audio&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;WvYm&quot;&gt;&lt;code&gt;--reference-audio&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;viCK&quot;&gt;&lt;code&gt;./ref/ref.wav&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;AeX3&quot;&gt;Аудио-референс для тембральной идентичности&lt;/p&gt;
  &lt;p id=&quot;aQ72&quot;&gt;&lt;code&gt;--output&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;eCSx&quot;&gt;&lt;code&gt;./output/anime_18.wav&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;Vqfu&quot;&gt;Путь к выходному файлу&lt;/p&gt;
  &lt;p id=&quot;WIPA&quot;&gt;&lt;code&gt;--model-path&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;Gjg0&quot;&gt;&lt;code&gt;./models/VoxCPM2&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;YCvs&quot;&gt;Локальный каталог с весами модели&lt;/p&gt;
  &lt;p id=&quot;6f01&quot;&gt;&lt;code&gt;--device&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;93G5&quot;&gt;&lt;code&gt;mps&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;kQWd&quot;&gt;Платформа на которой мы играемся&lt;/p&gt;
  &lt;p id=&quot;KT3S&quot;&gt;&lt;code&gt;--no-optimize&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;Y1j8&quot;&gt;&lt;em&gt;без значения&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;sXTW&quot;&gt;Отключение &lt;code&gt;torch.compile&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;B0ER&quot;&gt;&lt;code&gt;--cfg-value&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;VLUk&quot;&gt;&lt;code&gt;1.8&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;NOvi&quot;&gt;Значение Classifier-Free Guidance&lt;/p&gt;
  &lt;p id=&quot;wbf1&quot;&gt;&lt;code&gt;--inference-timesteps&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;YXSN&quot;&gt;&lt;code&gt;20&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;FXOK&quot;&gt;Количество шагов диффузионного декодера&lt;/p&gt;
  &lt;p id=&quot;830G&quot;&gt;&lt;code&gt;--normalize&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;BdLc&quot;&gt;&lt;em&gt;без значения&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;dlwR&quot;&gt;Нормализация громкости выхода&lt;/p&gt;
  &lt;p id=&quot;AvqR&quot;&gt;&lt;code&gt;--no-denoiser&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;THKW&quot;&gt;&lt;em&gt;без значения&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;envz&quot;&gt;Отключение модуля ZipEnhancer&lt;/p&gt;
  &lt;h3 id=&quot;результат&quot;&gt;Результат&lt;/h3&gt;
  &lt;p id=&quot;V13l&quot;&gt;На выходе получился файл 35.02. Послушать его можно ниже:&lt;/p&gt;
  &lt;p id=&quot;1m1X&quot;&gt;&lt;a href=&quot;https://blog.tatarinovms.space/audio/voxcpm/output.mp3&quot; target=&quot;_blank&quot;&gt;Скачать запись&lt;/a&gt;&lt;/p&gt;
  &lt;figure id=&quot;AdV3&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/TS3jRcnweWY?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;ютуб&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;p4F9&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://rutube.ru/play/embed/e9b02da8de79e9494f3959cfece86918/&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;рутуб&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;9sta&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://vk.com/video_ext.php?oid=-230469137&amp;id=456239119&amp;autoplay=0&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;вк видео&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;FYKn&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;литература-для-изучения&quot;&gt;Литература для изучения&lt;/h2&gt;
  &lt;ul id=&quot;bt54&quot;&gt;
    &lt;li id=&quot;Baz8&quot;&gt;GitHub репозиторий: &lt;a href=&quot;https://github.com/OpenBMB/VoxCPM&quot; target=&quot;_blank&quot;&gt;https://github.com/OpenBMB/VoxCPM&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;KkuA&quot;&gt;Страница модели на Hugging Face: &lt;a href=&quot;https://huggingface.co/openbmb/VoxCPM2&quot; target=&quot;_blank&quot;&gt;https://huggingface.co/openbmb/VoxCPM2&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>beaverclan:synctogit</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/synctogit?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>Синхронизация кода в два репозитория одновременно</title><published>2026-04-21T19:28:52.008Z</published><updated>2026-04-21T19:28:52.008Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/6c/4f/6c4f1c6d-5012-4a37-8ea0-d35943788975.png"></media:thumbnail><category term="blog" label="Blog"></category><summary type="html">&lt;img src=&quot;https://img4.teletype.in/files/f4/7d/f47d57b0-4b14-4c17-b2c1-f538fb36e8ad.png&quot;&gt;В условиях турбулентной работы облачных сервисов (снова так скажем) вопрос избыточности хранения кода становится актуальным. Держать проект только на GitHub — это риск. Решением может стать зеркалирование кода в другой сервис, например, на GitVerse.</summary><content type="html">
  &lt;figure id=&quot;pUWv&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f4/7d/f47d57b0-4b14-4c17-b2c1-f538fb36e8ad.png&quot; width=&quot;1424&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;r3zy&quot;&gt;В условиях турбулентной работы облачных сервисов (снова так скажем) вопрос избыточности хранения кода становится актуальным. Держать проект только на GitHub — это риск. Решением может стать зеркалирование кода в другой сервис, например, на GitVerse.&lt;/p&gt;
  &lt;p id=&quot;l7KB&quot;&gt;Обычно мы привыкли, что один &lt;code&gt;remote&lt;/code&gt; (например, &lt;code&gt;origin&lt;/code&gt;) привязан к одному URL. Но Git позволяет добавить несколько URL для push-операций в один remote.&lt;/p&gt;
  &lt;h3 id=&quot;PajP&quot;&gt;Как это настроить&lt;/h3&gt;
  &lt;p id=&quot;1jAd&quot;&gt;Если у вас уже есть основной репозиторий на GitHub, достаточно добавить второй URL для отправки данных:&lt;/p&gt;
  &lt;pre id=&quot;QRad&quot;&gt;git remote set-url --add --push origin git@gitverse.ru:tatarinovms/ShadowRocketSimpleConfig.git
&lt;/pre&gt;
  &lt;p id=&quot;SQC6&quot;&gt;Теперь при выполнении команды &lt;code&gt;git push origin&lt;/code&gt; ваши изменения полетят сразу в оба репозитория.&lt;/p&gt;
  &lt;h3 id=&quot;hnjv&quot;&gt;Нюансы с конфликтами&lt;/h3&gt;
  &lt;p id=&quot;oYBm&quot;&gt;Главная проблема возникает, когда в одном из зеркал есть изменения, которых нет в другом (например, вы отредактировали README прямо в веб-интерфейсе GitVerse). В этом случае обычный push будет отклонен.&lt;/p&gt;
  &lt;p id=&quot;v8pg&quot;&gt;Решить это можно через создание временного remote для «проблемного» зеркала и слияние веток:&lt;/p&gt;
  &lt;ol id=&quot;fet7&quot;&gt;
    &lt;li id=&quot;lb7T&quot;&gt;Добавляем зеркало как отдельный remote:&lt;code&gt;git remote add gitverse git@gitverse.ru:tatarinovms/ShadowRocketSimpleConfig.git &lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;YDZ7&quot;&gt;Подтягиваем изменения, разрешая несвязанные истории:&lt;code&gt;git pull gitverse main --no-rebase --allow-unrelated-histories &lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;FNnm&quot;&gt;После разрешения конфликтов снова пушим всё в &lt;code&gt;origin&lt;/code&gt;.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;jKqx&quot;&gt;Теперь код синхронизирован, а вы спите спокойно, зная, что копия вашего проекта лежит на разных площадках.&lt;/p&gt;

</content></entry><entry><id>beaverclan:podsync</id><link rel="alternate" type="text/html" href="https://teletype.in/@beaverclan/podsync?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=beaverclan"></link><title>Podsync - YouTube канал в подкаст-приемник</title><published>2026-04-12T14:01:27.349Z</published><updated>2026-04-12T14:01:27.349Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/07/93/0793e1f1-591a-48a0-bd29-95d73c38e184.png"></media:thumbnail><category term="blog" label="Blog"></category><summary type="html">&lt;img src=&quot;https://blog.tatarinovms.space/images/posts/podsync/logo.webp&quot;&gt;Podsync — маленький проектик на go, который преобразует каналы с YouTube или Vimeo в обычные подкаст-фиды (RSS). Идея проста: у меня есть каналы, которые я больше слушаю, чем смотрю, и мне хотелось бы делать это в моём подкаст-приёмнике. Гайд будет на Debian-based системы.</summary><content type="html">
  &lt;figure id=&quot;j1gZ&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://blog.tatarinovms.space/images/posts/podsync/logo.webp&quot; width=&quot;1344&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;JCSQ&quot;&gt;Podsync — маленький проектик на go, который преобразует каналы с YouTube или Vimeo в обычные подкаст-фиды (RSS). Идея проста: у меня есть каналы, которые я больше слушаю, чем смотрю, и мне хотелось бы делать это в моём подкаст-приёмнике. Гайд будет на Debian-based системы.&lt;/p&gt;
  &lt;h2 id=&quot;как-это-работает&quot;&gt;Как это работает&lt;/h2&gt;
  &lt;p id=&quot;lkiv&quot;&gt;Принцип работы Podsync довольно простой:&lt;/p&gt;
  &lt;ol id=&quot;LBrG&quot;&gt;
    &lt;li id=&quot;H2nY&quot;&gt;В конфиге прописываем каналы&lt;/li&gt;
    &lt;li id=&quot;Hd2o&quot;&gt;Podsync по расписанию проверяет обновления&lt;/li&gt;
    &lt;li id=&quot;ySm7&quot;&gt;Скачивает новые видео через yt-dlp и конвертирует их в аудио в MP3 через ffmpeg или оставляет видео. Тут уж как хотите.&lt;/li&gt;
    &lt;li id=&quot;0D3o&quot;&gt;Генерирует RSS-фид, доступный по HTTP/HTTPS&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;UXGH&quot;&gt;Вы просто добавляете ссылку вида &lt;code&gt;https://your-domain.com/feed_id.xml&lt;/code&gt; в подкаст-клиент — и всё работает.&lt;/p&gt;
  &lt;h2 id=&quot;установка-зависимостей&quot;&gt;Установка зависимостей&lt;/h2&gt;
  &lt;p id=&quot;tOdq&quot;&gt;Для работы Podsync нужны &lt;code&gt;yt-dlp&lt;/code&gt;, &lt;code&gt;ffmpeg&lt;/code&gt; и &lt;code&gt;deno&lt;/code&gt; (как JS runtime для yt-dlp на всякий случай):&lt;/p&gt;
  &lt;pre id=&quot;Mbyk&quot;&gt;apt update &amp;amp;&amp;amp; apt install -y yt-dlp ffmpeg curl
&lt;/pre&gt;
  &lt;p id=&quot;XTC9&quot;&gt;Deno устанавливается через официальный скрипт:&lt;/p&gt;
  &lt;pre id=&quot;Y1O8&quot;&gt;curl -fsSL https://deno.land/install.sh | sh
&lt;/pre&gt;
  &lt;p id=&quot;7MxG&quot;&gt;Также понадобится Go, если планируете собирать из исходников:&lt;/p&gt;
  &lt;pre id=&quot;Zeyp&quot;&gt;apt install -y golang
&lt;/pre&gt;
  &lt;h2 id=&quot;установка-podsync&quot;&gt;Установка Podsync&lt;/h2&gt;
  &lt;h3 id=&quot;вариант-a-сборка-из-исходников&quot;&gt;Вариант A: Сборка из исходников&lt;/h3&gt;
  &lt;pre id=&quot;retv&quot;&gt;git clone https://github.com/mxpv/podsync /mnt/dietpi_userdata/podsync
cd /mnt/dietpi_userdata/podsync
make
&lt;/pre&gt;
  &lt;h3 id=&quot;вариант-бэ-готовый-бинарь&quot;&gt;Вариант Бэ: Готовый бинарь&lt;/h3&gt;
  &lt;p id=&quot;U8Wn&quot;&gt;Скачиваем с &lt;a href=&quot;https://github.com/mxpv/podsync/releases&quot; target=&quot;_blank&quot;&gt;GitHub Releases&lt;/a&gt;:&lt;/p&gt;
  &lt;pre id=&quot;SeE6&quot;&gt;cd /mnt/dietpi_userdata/podsync
curl -L -o podsync &amp;quot;https://github.com/mxpv/podsync/releases/download/v2.8.0/podsync-v2.8.0-linux-amd64&amp;quot;
chmod +x podsync
&lt;/pre&gt;
  &lt;h3 id=&quot;вариант-цэ-docker&quot;&gt;Вариант Цэ: Docker&lt;/h3&gt;
  &lt;p id=&quot;jZPr&quot;&gt;Если предпочитаете контейнеры:&lt;/p&gt;
  &lt;pre id=&quot;7wvj&quot;&gt;services:
  podsync:
    image: ghcr.io/mxpv/podsync
    container_name: podsync
    volumes:
      - ./data:/app/data/
      - ./db:/app/db/
      - ./config.toml:/app/config.toml
    ports:
      - 8181:8080
&lt;/pre&gt;
  &lt;p id=&quot;SFhS&quot;&gt;Запуск:&lt;/p&gt;
  &lt;pre id=&quot;1PpR&quot;&gt;docker compose up -d
&lt;/pre&gt;
  &lt;h2 id=&quot;youtube-data-api-v3-ключ&quot;&gt;YouTube Data API v3 ключ&lt;/h2&gt;
  &lt;p id=&quot;YnNI&quot;&gt;Ключевой момент — для работы Podsync нужен &lt;strong&gt;YouTube Data API v3 ключ&lt;/strong&gt;. Без него парсинг каналов не работает.&lt;/p&gt;
  &lt;p id=&quot;D3X8&quot;&gt;Получить ключ можно здесь: &lt;a href=&quot;https://developers.google.com/youtube/registering_an_application&quot; target=&quot;_blank&quot;&gt;https://developers.google.com/youtube/registering_an_application&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;if7x&quot;&gt;В конфиге нужно указать ключ в секции:&lt;/p&gt;
  &lt;pre id=&quot;nujC&quot;&gt;[tokens]
youtube = &amp;quot;YOUR_YOUTUBE_API_KEY&amp;quot;
&lt;/pre&gt;
  &lt;p id=&quot;y8yT&quot;&gt;Или даже несколько для ротации:&lt;/p&gt;
  &lt;pre id=&quot;2DlI&quot;&gt;youtube = [&amp;quot;KEY1&amp;quot;, &amp;quot;KEY2&amp;quot;, &amp;quot;KEY3&amp;quot;]
&lt;/pre&gt;
  &lt;h2 id=&quot;настройка-конфигурации&quot;&gt;Настройка конфигурации&lt;/h2&gt;
  &lt;p id=&quot;rgyM&quot;&gt;Собственно и сам конфиг. Создаём файл &lt;code&gt;config.toml&lt;/code&gt; на основе примера:&lt;/p&gt;
  &lt;pre id=&quot;Jzne&quot;&gt;cp /mnt/dietpi_userdata/podsync/config.toml.example /mnt/dietpi_userdata/podsync/config.toml
nano /mnt/dietpi_userdata/podsync/config.toml
&lt;/pre&gt;
  &lt;p id=&quot;cJUH&quot;&gt;Для примера:&lt;/p&gt;
  &lt;pre id=&quot;n90n&quot;&gt;[server]
port = 8181
hostname = &amp;quot;https://poddown.tatarinovlovesbeaver.su&amp;quot;

[cleanup]
keep_last = 2

[storage]
  [storage.local]
  data_dir = &amp;quot;/mnt/dietpi_userdata/podsync/data&amp;quot;

[tokens]
youtube = &amp;quot;тут ваш ключ из пункта выше&amp;quot;

[feeds]
    [feeds.MaximTatarinov]
    url = &amp;quot;https://www.youtube.com/@MaximTatarinov&amp;quot;
    format = &amp;quot;video&amp;quot;
    update_period = &amp;quot;8h&amp;quot;
    page_size = 5
    youtube_dl_args = [&amp;quot;--js-runtimes&amp;quot;, &amp;quot;deno:/root/.deno/bin/deno&amp;quot;]

[log]
filename = &amp;quot;podsync.log&amp;quot;
max_size = 50
max_age = 30
max_backups = 1
compress = true
debug = false
&lt;/pre&gt;
  &lt;p id=&quot;MW7H&quot;&gt;Конфиг готов.&lt;/p&gt;
  &lt;h2 id=&quot;запуск-как-systemd-сервис&quot;&gt;Запуск как systemd-сервис&lt;/h2&gt;
  &lt;p id=&quot;b0c1&quot;&gt;Чтобы Podsync работал в фоне и запускался автоматически, создаём сервис:&lt;/p&gt;
  &lt;pre id=&quot;FSD8&quot;&gt;nano /etc/systemd/system/podsync.service
&lt;/pre&gt;
  &lt;pre id=&quot;WNoQ&quot;&gt;[Unit]
Description=Podsync
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/mnt/dietpi_userdata/podsync/bin/podsync
WorkingDirectory=/mnt/dietpi_userdata/podsync
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
Environment=&amp;quot;PATH=/root/.deno/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&amp;quot;

[Install]
WantedBy=multi-user.target
&lt;/pre&gt;
  &lt;p id=&quot;ajdG&quot;&gt;Активируем и запускаем:&lt;/p&gt;
  &lt;pre id=&quot;8h33&quot;&gt;systemctl daemon-reload
systemctl enable podsync
systemctl start podsync
&lt;/pre&gt;
  &lt;p id=&quot;JPEE&quot;&gt;Проверить статус:&lt;/p&gt;
  &lt;pre id=&quot;HBrk&quot;&gt;systemctl status podsync
journalctl -u podsync -f
&lt;/pre&gt;
  &lt;h2 id=&quot;reverse-proxy-через-nginx&quot;&gt;Reverse proxy через nginx&lt;/h2&gt;
  &lt;p id=&quot;EKGa&quot;&gt;Podsync у меня работает без TLS, поэтому HTTPS у нас будет обрабатывать nginx. Конфиг для сайта:&lt;/p&gt;
  &lt;pre id=&quot;YBhW&quot;&gt;server {
    listen 80;
    listen [::]:80;
    server_name poddown.tatarinovlovesbeaver.su;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    listen 443 quic;
    listen [::]:443 quic;
    quic_retry on;
    quic_gso on;
    add_header Alt-Svc &amp;#x27;h3=&amp;quot;:443&amp;quot;; ma=86400&amp;#x27; always;

    server_name poddown.tatarinovlovesbeaver.su;

    ssl_certificate /etc/letsencrypt/live/poddown.tatarinovlovesbeaver.su/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/poddown.tatarinovlovesbeaver.su/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1:8181;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
&lt;/pre&gt;
  &lt;p id=&quot;sBDX&quot;&gt;Применить:&lt;/p&gt;
  &lt;pre id=&quot;kWA0&quot;&gt;nginx -t &amp;amp;&amp;amp; systemctl reload nginx
&lt;/pre&gt;
  &lt;h2 id=&quot;фильтры-и-тонкая-настройка&quot;&gt;Фильтры и тонкая настройка&lt;/h2&gt;
  &lt;p id=&quot;shWg&quot;&gt;Podsync позволяет не просто скачивать всё подряд, а выбирать контент по правилам. Например, скачивать только эпизоды, содержащие «обзор» и длительностью до 2 часов:&lt;/p&gt;
  &lt;pre id=&quot;ANlH&quot;&gt;[feeds]
    [feeds.ID1]
    url = &amp;quot;https://www.youtube.com/@channel&amp;quot;
    format = &amp;quot;audio&amp;quot;
    filters = { title = &amp;quot;обзор&amp;quot;, max_duration = 7200, max_age = 30 }
&lt;/pre&gt;
  &lt;p id=&quot;cae8&quot;&gt;Доступные фильтры:&lt;/p&gt;
  &lt;p id=&quot;kQBP&quot;&gt;Параметр&lt;/p&gt;
  &lt;p id=&quot;yhPa&quot;&gt;Описание&lt;/p&gt;
  &lt;p id=&quot;Qm25&quot;&gt;&lt;code&gt;title&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;qdcf&quot;&gt;Regex для совпадения в заголовке&lt;/p&gt;
  &lt;p id=&quot;kOdT&quot;&gt;&lt;code&gt;not_title&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;636V&quot;&gt;Regex для исключения по заголовку&lt;/p&gt;
  &lt;p id=&quot;wD2V&quot;&gt;&lt;code&gt;description&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;tgd7&quot;&gt;Regex для совпадения в описании&lt;/p&gt;
  &lt;p id=&quot;ab6m&quot;&gt;&lt;code&gt;not_description&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;a0Aa&quot;&gt;Regex для исключения по описанию&lt;/p&gt;
  &lt;p id=&quot;IZ99&quot;&gt;&lt;code&gt;min_duration&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;5KCC&quot;&gt;Минимальная длительность (секунды)&lt;/p&gt;
  &lt;p id=&quot;ORoW&quot;&gt;&lt;code&gt;max_duration&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;EvTJ&quot;&gt;Максимальная длительность (секунды)&lt;/p&gt;
  &lt;p id=&quot;Ecnz&quot;&gt;&lt;code&gt;min_age&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;Ei9M&quot;&gt;Минимальный возраст (дни)&lt;/p&gt;
  &lt;p id=&quot;bFNo&quot;&gt;&lt;code&gt;max_age&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;2Iyo&quot;&gt;Максимальный возраст (дни)&lt;/p&gt;
  &lt;p id=&quot;TOTF&quot;&gt;Также можно задать кастомный формат видео:&lt;/p&gt;
  &lt;pre id=&quot;9DgJ&quot;&gt;[feeds]
    [feeds.MaximTatarinov]
    format = &amp;quot;custom&amp;quot;
    custom_format = { youtube_dl_format = &amp;quot;bestaudio[ext=m4a]&amp;quot;, extension = &amp;quot;m4a&amp;quot; }
&lt;/pre&gt;
  &lt;h2 id=&quot;итог&quot;&gt;Итог&lt;/h2&gt;
  &lt;p id=&quot;G2uO&quot;&gt;RSS-лента доступна по адресу:&lt;/p&gt;
  &lt;pre id=&quot;TewD&quot;&gt;https://poddown.tatarinovlovesbeaver.su/MaximTatarinov.xml
&lt;/pre&gt;
  &lt;p id=&quot;aoWA&quot;&gt;Подставляем её в ваш подкаст-клиент и вуаля!&lt;/p&gt;

</content></entry></feed>