﻿<rss version="2.0">
    <channel>    
        <title>Влад Костянецкий</title>
        <description>Привет! Меня зовут Влад, я — разработчик приложений для бизнеса.</description>
        <language>ru</language>
        <link>https://kostyanetsky.ru</link>
        
        <lastBuildDate>Sat, 22 Aug 2026 22:23:03 +0000</lastBuildDate>
        
        
        <item>
            <title>Феномен Егоровой</title>
            <link>https://kostyanetsky.ru/notes/egorova</link>
            <guid isPermaLink="false">note-egorova</guid>
            <pubDate>Sat, 22 Aug 2026 22:23:03 +0000</pubDate>
            <description>&lt;p&gt;Последние полгода постоянно &lt;a href=&#34;https://kostyanetsky.ru/notes/autosummary&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;использую&lt;/a&gt; Whisper для расшифровки встреч. Заметил забавный эффект: чем толще модель, тем лучше она распознаёт речь и тем увереннее несёт бред там, где речи нет.&lt;/p&gt;
&lt;p&gt;Например, такое бывает в начале вебинара или встречи, пока участники собираются. Тихо, все молчат, разве что кто-нибудь шумно тянет кофе. И Whisper внезапно начинает выдавать что-то такое:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Редактор субтитров А.Синецкая Корректор А.Егорова&lt;br/&gt;
Редактор субтитров А.Синецкая Корректор А.Егорова&lt;br/&gt;
Редактор субтитров А.Синецкая Корректор А.Егорова&lt;br/&gt;
Редактор субтитров А.Синецкая Корректор А.Егорова  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;И что хуже, &lt;strong&gt;продолжает выдавать это даже тогда, когда начинается уже вполне разборчивая речь&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Это здорово раздражало, так что пришлось разобраться.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Да кто такая эта ваша Егорова&#34; src=&#34;https://kostyanetsky.ru/notes/egorova/egorova.png&#34;/&gt;&lt;/p&gt;
&lt;h2&gt;Почему тишина так распознается?&lt;/h2&gt;
&lt;p&gt;Под капотом у Whisper — мощная языковая модель, которая пытается подобрать наиболее вероятный текст с учётом аудио и уже распознанного контекста. В общем случае это работает как надо: модель хорошо понимает речь, контекст, имена и сложные фразы. &lt;/p&gt;
&lt;p&gt;Но если на входе тишина, шум или что-то невнятное, звук почти перестаёт быть ей полезен. И вот тут модель начинает гадать: какой текст здесь вообще мог бы быть, хм? Обучена она на гигантском датасете аудио с текстовыми расшифровками, которые OpenAI натаскала со всего интернета (порядка 700 тысяч часов, если не путаю).&lt;/p&gt;
&lt;p&gt;Среди этого добра, полагаю, было полным-полно видео с субтитрами — а это штука такая, грязная. Во время тишины в сабах вполне может мелькать имя переводчика, редактора, название студии, «спасибо за просмотр» и прочий мусор, которого в аудио вообще нет. &lt;/p&gt;
&lt;p&gt;Вот так, думаю, Синецкая с Егоровой и вошли в историю. Над чем они работали, я найти не смог, но, видимо, надпись с отсылкой на них маячила в сабах достаточно часто, чтобы Whisper поставил знак равенства между ними и тишиной. &lt;/p&gt;
&lt;h2&gt;Почему так распознаётся не только тишина?&lt;/h2&gt;
&lt;p&gt;Угу, если бы всего лишь получали шум во время пауз, это вообще не было бы проблемой: мусорный фрагмент текста известен и его можно просто выкидывать из выдачи. Хуже всего тут то, что ошибка распознавания портит контекст модели — упрощая, Whisper распознаёт тишину как Егорову, подсовывает этот результат себе же как контекст следующего куска и едет дальше с этим знанием.&lt;/p&gt;
&lt;p&gt;Следующий кусок, допустим, опять Егорова, и потом тоже, и потом... Когда спикер наконец-то начинает говорить, ему нужно начать ОЧЕНЬ внятно, чтобы модель согласилась, что да, это уже речь, а не Егорова, набравшая силу на двадцати кусках до него. В результате модель способна застрять в этом состоянии очень надолго.&lt;/p&gt;
&lt;p&gt;Проблеме сто лет (ну ладно, четыре года) и она существует для множества языков. Русский, кстати, &lt;a href=&#34;https://github.com/openai/whisper/discussions/928#discussioncomment-5372187&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;выбивается&lt;/a&gt; из общего ряда — если итальянцы, французы и испанцы видят скучное «Субтитры созданы сообществом Amara.org», то у нас, так сказать, свой фэндом.&lt;/p&gt;
&lt;h2&gt;Как бороться?&lt;/h2&gt;
&lt;p&gt;Вообще считается, что надо тюнить инференс: сбрасывать контекст после длинных пауз, играться с &lt;code&gt;no_speech_threshold&lt;/code&gt;, &lt;code&gt;condition_on_previous_text&lt;/code&gt;, предварительно отрезать тишину с помощью VAD и так далее. До VAD я не добрался, но остальные варианты пробовал — действительно можно добиться вполне сносного результата на конкретном проблемном видео.&lt;/p&gt;
&lt;p&gt;Однако мне этот вариант не подошел: мне нужно распознавать самые разные видео — записи встреч, лекции, телефонные разговоры, что угодно. Комбинация приёмов, подобранная для одного видео, не работает для другого. Из инженерного азарта я пробовал собирать обвязку в духе «прогнать видео через три разные комбинации приёмов, а потом проанализировать результат и выбрать тот, где концентрация Егоровой пожиже», но это всё равно работало так себе.&lt;/p&gt;
&lt;p&gt;Так что я выбрал другое решение: &lt;strong&gt;использовать модель поглупее!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Серьёзно, это работает. По крайней мере на моих видео Whisper Small сваливается в repetition loop на тишине сильно реже. Видимо, более слабой модели сложнее уверенно вывести мусорный паттерн, поэтому на тишине она просто не выводит ничего.&lt;/p&gt;
&lt;p&gt;Упрощая,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whisper Small: Эээ... Ничего не слышу. Непонятно.&lt;/li&gt;
&lt;li&gt;Whisper Medium: Эээ... Ничего не слышу... &lt;em&gt;(напрягает свои параметры)&lt;/em&gt; А! Знаю! &lt;em&gt;(вступают фанфары)&lt;/em&gt; Это ж Егорова!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;:D Горе от ума, буквально.&lt;/p&gt;
&lt;p&gt;Качество расшифровки у Whisper Small получается, конечно, пониже — больше криво распознанных слов, менее связно, но &lt;s&gt;это лучше, чем когда треть звука слопано Синецкой, а остальное поглодала Егорова&lt;/s&gt; результат в среднем более предсказуем.&lt;/p&gt;
&lt;p&gt;Кроме того, его все равно нужно потом загнать в условный ChatGPT, чтобы собрать саммари, а для этого гигачада восстановить контекст диалога вообще не вопрос, даже если фрагменты реплик потеряны.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Мику-питомец для Codex</title>
            <link>https://kostyanetsky.ru/notes/miku-codex-pet</link>
            <guid isPermaLink="false">note-miku-codex-pet</guid>
            <pubDate>Tue, 18 Aug 2026 09:17:10 +0000</pubDate>
            <description>&lt;p&gt;В десктопном &lt;a href=&#34;https://openai.com/codex&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Codex&lt;/a&gt; есть питомцы — пиксельные персонажи, которые рендерятся поверх UI и показывают, чем занят агент: работает — идёт, ждёт ответа — зовёт пользователя, застрял — жмурится и так далее. Общая идея в том, что пользователь запускает какой-нибудь флоу, переключается на свои дела и краем глаза видит, как там всё идёт.&lt;/p&gt;
&lt;p&gt;Фича не особенно полезная, но забавная. Правда, встроенные питомцы мне не зашли; полез смотреть работы сообщества и внезапно на ровном месте разогнался сделать своего — на базе дизайна Хацуне Мику из &lt;a href=&#34;https://chaim-videogames.itch.io/mikun-pop&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Miku&#39;n POP&lt;/a&gt;, старого-престарого платформера.&lt;/p&gt;
&lt;p&gt;Оказалось, не особенно сложно. Спрайты я взял из &lt;a href=&#34;https://github.com/CharlesWiiFlowers/MikuPet&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;MikuPet&lt;/a&gt; (автор использует тот же дизайн из Miku&#39;n POP), а формат самого питомца довольно понятный (да и благодаря тому же Codex копаться в нём особо не пришлось). Дольше &lt;a href=&#34;https://github.com/vkostyanetsky/MikuCodexPet/blob/main/ATTRIBUTION.ru.md&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;разбирался&lt;/a&gt;, чей там арт, на каких условиях его можно переиспользовать и так далее.&lt;/p&gt;
&lt;p&gt;Питомца можно &lt;a href=&#34;https://github.com/vkostyanetsky/MikuCodexPet/releases&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;скачать&lt;/a&gt; с GitHub, там же скриншот и &lt;a href=&#34;https://github.com/vkostyanetsky/MikuCodexPet&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;подробные описания&lt;/a&gt; того, что внутри барабанчика.&lt;/p&gt;
&lt;p&gt;Бесплатный бонус: &lt;a href=&#34;https://github.com/vkostyanetsky/MikuCodexPet/actions/workflows/release.yml&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;сборщик&lt;/a&gt; релизов в таком проекте можно назвать «Release pet» :)&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Obsidian Property Organizer</title>
            <link>https://kostyanetsky.ru/notes/obsidian-property-organizer</link>
            <guid isPermaLink="false">note-obsidian-property-organizer</guid>
            <pubDate>Sun, 09 Aug 2026 14:41:26 +0000</pubDate>
            <description>&lt;p&gt;Что точно стало лучше с появлением ИИ в инструментарии разработчиков — наконец-то появилась реальная возможность доделывать мелкие проекты. Я про всякие тулкиты, MVP-шки и идеи, которые раньше почти всегда отправлялись в стол: делать вроде хочется, но тратить несколько вечеров на очередную маленькую утилиту просто-напросто влом.&lt;/p&gt;
&lt;p&gt;Например, на прошлой неделе я навайбкодил себе &lt;a href=&#34;https://community.obsidian.md/plugins/property-organizer&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;плагин&lt;/a&gt; для Obsidian, который приводит в порядок свойства заметок. Если вкратце: для разных папок можно задать, какие свойства должны быть у заметок и в каком порядке. Плагин добавляет недостающие, убирает лишние и переставляет всё как положено — вместо того бардака, который я когда-то накидал на скорую руку и забыл поправить.&lt;/p&gt;
&lt;p&gt;В репозитории на Github есть &lt;a href=&#34;https://github.com/vkostyanetsky/ObsidianPropertyOrganizer/blob/main/README.ru.md&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;подробное описание&lt;/a&gt;, как это работает.&lt;/p&gt;
&lt;p&gt;Вроде бы мелочь, да? Поглаживание внутреннего перфекциониста. Но мне нравится порядок, а за три дня плагин успели скачать семьдесят человек.&lt;/p&gt;
&lt;p&gt;Привет вам, собратья по навязчивой любви к чистоте :)&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Автообновление для Timesheet</title>
            <link>https://kostyanetsky.ru/notes/timesheet-auto-refresh</link>
            <guid isPermaLink="false">note-timesheet-auto-refresh</guid>
            <pubDate>Sun, 26 Jul 2026 12:37:00 +0000</pubDate>
            <description>&lt;p&gt;Спонтанно вернулся к своему старому &lt;a href=&#34;https://github.com/vkostyanetsky/ObsidianTimesheet&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;плагину для Obsidian&lt;/a&gt;, который по daily notes за какой-то день выдаёт список задач и время, потраченное на каждую.&lt;/p&gt;
&lt;p&gt;В его коде был первородный баг: при изменении текста заметки блок плагина не перерисовывался самостоятельно. То есть добавляешь задачу, меняешь потраченное время или исправляешь описание, а отчёт продолжает показывать старые данные. Приходилось либо переоткрывать саму заметку, либо начинать редактирование блока, а потом отменять, чтобы затриггерить его рендер вручную. Это раздражало (и пахло велосипедом).&lt;/p&gt;
&lt;p&gt;Теперь блок плагина автоматически рендерится после изменений (только он, не вся заметка). Плюс есть небольшая задержка после ввода и проверка: если отчёт фактически не изменился, то рендера не будет вообще.&lt;/p&gt;
&lt;p&gt;Хотел ещё сразу обновить зависимости, всё-таки год прошёл, но... В NPM, знаете ли, всё тот же образцовый порядок. Каждая крошечная библиотека для сложения двух чисел непременно ссылается на десять соседних, каждый пакет соседскому забору двоюродный плетень и ни один просто так не заменишь: &lt;code&gt;npm audit&lt;/code&gt; ругается на любой чих. В общем, как надежно обновить зависимости так, чтобы не сломать сам плагин — я с наскока не понял.&lt;/p&gt;
&lt;p&gt;Ладно, это задача для завтрашнего меня.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Если кто-то его создаст</title>
            <link>https://kostyanetsky.ru/notes/if-anyone-builds-it</link>
            <guid isPermaLink="false">note-if-anyone-builds-it</guid>
            <pubDate>Sun, 28 Jun 2026 22:00:00 +0000</pubDate>
            <description>&lt;p&gt;В Corpus вышла на русском языке книга «&lt;a href=&#34;https://www.corpus.ru/products/ehliezer-yudkovskij-esli-kto-to-ego-sozdast-vse-pogibnut.htm&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Если кто-то его создаст — все погибнут&lt;/a&gt;» Элиезера Юдковского и Нейта Соареса. Оба — известные исследователи в области безопасности ИИ, AI alignment и рисков сверхинтеллекта.&lt;/p&gt;
&lt;p&gt;В книжке авторы внятно и последовательно объясняют, почему её название — не истерика, не преувеличение и не байт на лайки. Тезис простой и неприятный: если кто-нибудь на планете действительно создаст AGI или ASI на технологиях, близких к нынешним — человечеству хана.&lt;/p&gt;
&lt;p&gt;Соареса я раньше не читал, а вот в Юдковском всегда сочетались два редких качества: экспертность в теме и способность рассуждать о ней человеческим языком, не проваливаясь в заумь каждые тридцать секунд. То есть вам не обязательно иметь профильный бэкграунд: тут явно проделана куча работы просто для того, чтобы текст был понятен аудитории без кандидатской по прикладной математике.&lt;/p&gt;
&lt;p&gt;Короче, книжка классная. Забыл уже, когда в последний раз читал что-то запоем, на одном дыхании. Есть на Озоне, в Читай-городе, есть даже в пиратских бухтах (осуждаю, но если ваш фрегат с черным флагом уже припаркован у подъезда, то что я могу поделать) :)&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Номер года в литерале типа дата превышает 3999</title>
            <link>https://kostyanetsky.ru/notes/date-literal-exceeds-3999-once-again</link>
            <guid isPermaLink="false">note-date-literal-exceeds-3999-once-again</guid>
            <pubDate>Sat, 28 Mar 2026 19:42:53 +0000</pubDate>
            <description>&lt;p&gt;Про ошибку в названии заметки я уже как-то &lt;a href=&#34;https://kostyanetsky.ru/notes/date-literal-exceeds-3999&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;писал&lt;/a&gt;. Напомню суть: платформа не переваривает даты позже 3999 года (на практике начинает стрелять с 3999-12-01). Теоретически такие даты вообще нельзя записать, но &lt;s&gt;если очень хочется&lt;/s&gt; из-за ошибок в прикладном коде (и в коде самой платформы) это всё-таки возможно и время от времени случается. &lt;/p&gt;
&lt;p&gt;Обычные симптомы — перестают работать какие-то отчёты, не проводятся какие-то документы, падает пересчёт итогов. В общем, страдает любой код, который трогает записи с проблемными датами.&lt;/p&gt;
&lt;p&gt;Способ лечения, который я рамочно описал в заметке по ссылке выше — рабочий, но сравнительно медленный: нужно настроить ТЖ, собрать и распарсить результаты. Между тем, платформа падает на первом же обращении к битой дате, а их может быть много и валяться они могут в разных таблицах. То есть может потребоваться несколько подходов к снаряду: проверили, получили ошибку, исправили, проверили, получили следующую...&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Thank You, Mario!&#34; src=&#34;https://kostyanetsky.ru/notes/date-literal-exceeds-3999-once-again/thanks.jpg&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Желая решать проблему как-нибудь побыстрее, несколько лет назад я написал &lt;a href=&#34;https://gist.github.com/vkostyanetsky/a58ff201d2a87a35e70c4c8f4112ad4c&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;запрос для PostgreSQL&lt;/a&gt;. Общая идея:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ищем в базе данных все поля с датами.&lt;/li&gt;
&lt;li&gt;Строим мегазапрос к таким полям (ищем даты, которые выходят за лимит 1С).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;То есть этот запрос генерирует другой запрос, да. Выполняем его и получаем полную картинку проблемы: список таблиц с некорректными датами. Дальше уже дело техники — смотрим, что за таблицы и решаем, как быть. В нашем случае проблемные даты иногда возникают в итогах и оборотах, так что их можно просто удалять и пересчитывать итоги через штатные инструменты.&lt;/p&gt;
&lt;p&gt;Почему действуем на уровне СУБД? Ну, средствами 1С такой номер не отколоть — напомню, платформа падает при попытке потрогать проблемные записи. Это касается любого взаимодействия, включая чтение. Кроме того, в данном случае работать напрямую быстрее и удобнее.&lt;/p&gt;
&lt;p&gt;На днях я переписал этот &lt;a href=&#34;https://gist.github.com/vkostyanetsky/5990a16caacc4a9057b577c6a5694512&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;запрос для MS SQL&lt;/a&gt;. Вышло длиннее (в силу особенностей этой СУБД), но идея та же.&lt;/p&gt;
&lt;p&gt;Если будете использовать, имейте в виду, что:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Поле &lt;code&gt;_Fld626&lt;/code&gt; в тексте запроса — разделитель для фреша. В вашей базе может называться по-другому или вообще отсутствовать.&lt;/li&gt;
&lt;li&gt;Запрос написан для базы со сдвигом в 2000 лет. Если в вашей базе сдвига нет, нужно скорректировать условие (см. функцию &lt;code&gt;DATEADD()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Трюк с выводом в XML (см. &lt;code&gt;FOR XML&lt;/code&gt;) я добавил, чтобы не дать SSMS обрезать текст мегазапроса (показалось быстрее, чем возиться с приведением типов). Побочный эффект: в получившемся мегазапросе нужно заменить &lt;code&gt;&amp;amp;gt;&lt;/code&gt; на &lt;code&gt;&amp;gt;&lt;/code&gt;, прежде чем выполнять его.&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
        
        <item>
            <title>С побочным эффектом</title>
            <link>https://kostyanetsky.ru/notes/with-side-effect</link>
            <guid isPermaLink="false">note-with-side-effect</guid>
            <pubDate>Sun, 15 Mar 2026 12:24:12 +0000</pubDate>
            <description>&lt;p&gt;В последнем релизе &lt;a href=&#34;https://firstbit.ae&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;нашей ERP&lt;/a&gt; мы оптимизировали несколько тяжелых динамических списков (заказы, инвойсы, проформа инвойсы и так далее). Там накопился приличный техдолг, в основном — горы вспомогательных таблиц, прикрученных к основным запросам (контактная информация, технические реквизиты, остатки, обороты и так далее). В итоге даже в сравнительно небольших приложениях оптимизатор СУБД начинал выдавать бредни вместо планов запроса и мало-помалу платить за это ресурсами стало совсем неприятно.&lt;/p&gt;
&lt;p&gt;В общем, запатчили через несколько разных подходов, один из них — подгрузка дополнительных данных в обработчике &lt;code&gt;ПриПолученииДанныхНаСервере()&lt;/code&gt; (я про него недавно &lt;a href=&#34;https://kostyanetsky.ru/notes/desire-paths&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;вспоминал&lt;/a&gt;, кстати). Написали удобный фреймворк вокруг фичи, внедрили, потестировали и... В общем, сидим с кислыми минами. &lt;/p&gt;
&lt;p&gt;Нет, с производительностью и правда стало сильно лучше. Запрос к тяжелым виртуальным таблицам можно затюнить просто идеально. Проблема в другом: значения полей, которые заполняет этот обработчик, не пробрасываются в стандартные механики динамического списка. То есть для них не работает поиск, сортировка и группировка.&lt;/p&gt;
&lt;p&gt;Например, вводим значение, которое видим в колонке, а строка не находится. Или находятся не все строки. Или находятся строки, которые не должны были найтись. Для пользователя это выглядит отвратительно, ну баг и баг же: визуально-то такие поля никак не отличаются. Как ты ему объяснишь, что это особенность работы механизма платформы™? &lt;/p&gt;
&lt;p&gt;Исключишь такое поле из механизмов, которые с ними работать не могут — будет ещё чище. Например, попытаешься отсортировать — получишь здоровенную ошибку. Опять же, объяснить, почему на этой колонке с суммой вылетает ошибка, а на соседней сортировка прекрасно работает — задача со звездочкой.&lt;/p&gt;
&lt;p&gt;Блин, вот как можно было разработать такой замечательный концепт обработчика и настолько заруинить реализацию на уровне платформы?&lt;/p&gt;
&lt;p&gt;Неожиданно вспомнил Реддит. В некоторых сообществах популярны треды «придумай суперсилу, но с побочным эффектом». Типа, кто-то пишет в комментариях: я могу бегать со скоростью ветра! Ему отвечают: да, но не можешь тормозить. И так далее. Местами получается забавно.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Superpower&#34; src=&#34;https://kostyanetsky.ru/notes/with-side-effect/reddit.png&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Вот и мы с разработчиками платформы в таком же диалоге. Вы можете разогнать динамические списки (но UI будет вызывать у пользователей бешенство). Вы можете автоматом слать двоичные данные в бакет S3 (но потеряете их в один неосторожный клик). Вы можете телепортироваться куда угодно (но тратите столько времени, словно шли пешком). Вы можете превращаться (но только в пожилого мопса). У вас пышные, шелковистые волосы (но на заднице). &lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Икигай</title>
            <link>https://kostyanetsky.ru/notes/ikigai</link>
            <guid isPermaLink="false">note-ikigai</guid>
            <pubDate>Mon, 09 Mar 2026 22:01:43 +0000</pubDate>
            <description>&lt;p&gt;В японском языке есть замечательное слово «икигай». Это что-то вроде смысла жизни, но не в большом экзистенциальном понимании, а в более приземлённом и конкретном: источник внутренней энергии, источник радости. Ради чего хочется вставать по утрам, короче.&lt;/p&gt;
&lt;p&gt;Таких опор у человека может быть несколько, и у всех они свои. Кофе, кот, любимое ремесло, забота о близких, сад, прогулки, видеоигры...&lt;/p&gt;
&lt;p&gt;Я это к чему. Наткнулся на канал «&lt;a href=&#34;https://t.me/aleshkino_svoe&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Алёшкино своё&lt;/a&gt;». Его автор, насколько я понял, питерский юрист, который разводит породистых курочек и регулярно записывает видео то про конкретные породы, то про нюансы инкубации, то про кормление.&lt;/p&gt;
&lt;p&gt;Я вообще не в теме и птицами не интересуюсь, но поймал себя на том, что минут двадцать просто сидел и заворожённо слушал, не отрываясь. Работает почти как терапия, ей-богу. И, кажется, это вполне такой солидный икигай: дело, которое будешь любить так, как этот мужик любит своих курочек.&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Автосаммари</title>
            <link>https://kostyanetsky.ru/notes/autosummary</link>
            <guid isPermaLink="false">note-autosummary</guid>
            <pubDate>Sun, 08 Feb 2026 09:53:48 +0000</pubDate>
            <description>&lt;p&gt;Записывать все встречи я, судя по моим же &lt;a href=&#34;https://kostyanetsky.ru/notes/video-recording&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;заметкам&lt;/a&gt;, начал ещё в 2020-м. Видео всегда точнее памяти, а ткнуть на «Start Recording» в &lt;a href=&#34;https://obsproject.com&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;OBS&lt;/a&gt; — самый дешёвый способ не потерять какую-нибудь ценную инфу.&lt;/p&gt;
&lt;p&gt;Минусы, впрочем, очевидны — с видео нельзя быстро ухватить суть встречи, по нему невозможен быстрый поиск, оно много весит, в нём легко засветить что-то личное и так далее. Чтобы частично компенсировать это, я в течение встреч тезисно помечал ключевые моменты, а потом либо перекидывал в задачник, либо делал себе что-то вроде саммари: с кем встречался, что обсуждали, какие решения подобрали. Если что-то забыл или упустил детали — сверялся с видео.&lt;/p&gt;
&lt;p&gt;Однако этот метод тоже не идеален. Создание конспекта (даже тезисного) отъедает фокус от самой встречи. Кроме того, про какие-нибудь забытые по ходу дела подробности можно узнать слишком поздно.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Забыл&#34; src=&#34;https://kostyanetsky.ru/notes/autosummary/forgot.jpg&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Короче, пришёл к тому, что хороший вариант — просто извлекать из видео аудио разговора, превращать его в текст (нейронкой), а текст разговора — в детальное саммари по встрече (опять нейронка).&lt;/p&gt;
&lt;p&gt;Аудио проще всего выдрать через &lt;a href=&#34;https://www.ffmpeg.org&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;ffmpeg&lt;/a&gt; (консольная утилита для работы с аудио и видео). Ниже пример вызова (один аудиоканал, дискретизация 16 кГц + нормализация громкости):&lt;/p&gt;
&lt;pre&gt;
ffmpeg.exe -y -i &#34;D:\video.mkv&#34; -vn -ac 1 -ar 16000 -af loudnorm -c:a pcm_s16le &#34;D:\audio.wav&#34;
&lt;/pre&gt;
&lt;p&gt;Что до извлечения текста — я экспериментировал с &lt;a href=&#34;https://alphacephei.com/vosk/&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Vosk&lt;/a&gt; в связке с &lt;a href=&#34;https://github.com/benob/recasepunc&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;recasepunc&lt;/a&gt;, но про это без слёз не вспомнить. Даже комментировать не хочу. А вот &lt;s&gt;Боромир&lt;/s&gt; &lt;a href=&#34;https://openai.com/index/whisper&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Whisper&lt;/a&gt; (нейросеть от OpenAI, умеющая распознавать голос) ставится в фоне за 10 минут:&lt;/p&gt;
&lt;pre&gt;
py -3.10 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install setuptools wheel
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install openai-whisper
&lt;/pre&gt;
&lt;p&gt;Пример вызова:&lt;/p&gt;
&lt;pre&gt;
whisper &#34;D:\audio.wav&#34; --model small --language Russian --output_format txt
&lt;/pre&gt;
&lt;p&gt;На выходе получится текстовый файл с расшифровкой, который можно запихать в любой чатбот и получить вполне связное саммари. Его, конечно, всё ещё нужно вычитать — убрать ошибки и фантазии, что-то переформулировать — но это всё ещё сильно лучше создания конспекта на ходу.&lt;/p&gt;
&lt;p&gt;Вот, в общем-то, и весь метод. Остаётся написать простой скрипт, чтобы не дергать две команды вручную. Если вы тоже на Windows и вам лень вайбкодить, можете взять &lt;a href=&#34;https://gist.github.com/vkostyanetsky/4f4760097f1b417cc85d71d11662a642&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;мой скрипт&lt;/a&gt; и подогнать под себя.&lt;/p&gt;
&lt;p&gt;Скрипт ищет в своей папке первый попавшийся .mkv, прогоняет через ffmpeg + Whisper и сохраняет результат в ту же папку. Если будете использовать — обратите внимание, что он работает через &lt;a href=&#34;https://developer.nvidia.com/cuda&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;CUDA&lt;/a&gt; (на CPU тоже можно, но будет сильно медленнее) + скачанные модели Whisper он сохраняет не в дефолтный кэш, а в папку с текущим Python-окружением.&lt;/p&gt;
&lt;p&gt;(при желании можно прикрутить к нему вызов API или обращение к какой-нибудь модели в локальной &lt;a href=&#34;https://lmstudio.ai&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;LM Studio&lt;/a&gt;, но персонально для себя я решил — не, уже перебор)&lt;/p&gt;</description>
        </item>
        
        <item>
            <title>Новый UI в блоге</title>
            <link>https://kostyanetsky.ru/notes/new-ui</link>
            <guid isPermaLink="false">note-new-ui</guid>
            <pubDate>Sat, 17 Jan 2026 18:18:43 +0000</pubDate>
            <description>&lt;p&gt;На новогодних праздниках внезапно закусился и переписал UI блога. Хотел всего-то прикрутить поиск по заметкам: их уже довольно много и время от времени нужно что-то быстро выудить из кучи написанного (например, ссылку коллеге скинуть).&lt;/p&gt;
&lt;p&gt;Блог живёт на &lt;a href=&#34;https://pages.github.com&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Github Pages&lt;/a&gt;, так что выбор решений небогат: либо слать запрос в гугл, либо делать свой статический индекс и отдавать в браузер пользователя (пусть сам в нём роется). Я пошёл по второму пути: быстрее, управляемее &lt;s&gt;и можно самому покодить&lt;/s&gt;. При первом поиске &lt;a href=&#34;https://kostyanetsky.ru/notes.json&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;файл индекса&lt;/a&gt;, правда, нужно скачать, но что такое 200 Кб в современном интернете? Смешно.&lt;/p&gt;
&lt;p&gt;Ну а там как-то, знаете ли, пошло-поехало... Сначала не удавалось прикрутить к полю поиска &lt;a href=&#34;https://tachyons.io&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Tachyons&lt;/a&gt; — разозлился и переделал всё на &lt;a href=&#34;https://tailwindcss.com&#34; rel=&#34;noopener noreferrer&#34; target=&#34;_blank&#34;&gt;Tailwind&lt;/a&gt; (всё равно хотел попробовать, а случая всё никак не представлялось). Пока писал код для поиска — подумал, что логично сразу вкрутить в него теги, чтобы два раза не вставать. Очнулся с облаком тегов над заметками и сообразил, что тогда уж надо и с проектником то же самое сделать, только там не теги нужны, а стеки...&lt;/p&gt;
&lt;p&gt;В общем, получилось как в том меме из «Страха и отвращения в Лас-Вегасе». Сложно было остановиться. Осталось заставить себя писать в новый проектник: работы всегда дофига, и работа интересная, но если не писать о ней — кофе, всё тонет в кофе.&lt;/p&gt;</description>
        </item>
        
    </channel>
</rss>