Польское «Радио-3» (так называемая «Тройка») знаменито хорошей музыкой и интеллигентными ведущими. С другой стороны, оно страдает наличием громких и раздражающих рекламных блоков в трансляции, где обычно рекламируется какая-нибудь электроника или лекарство. Я слушаю «Тройку» почти постоянно на работе и дома, поэтому задался вопросом: как удалить рекламу? Кажется, мне удалось найти решение.
Цифровая обработка сигналов
Моя цель — создать приложение, которое приглушает рекламу. Коммерческий блок начинается и заканчивается джинглами, поэтому программа должна распознать эти конкретные звуки и выключить звук между ними.
Знаю, что данная область математики/информатики называется цифровой обработкой сигналов, но мне DSP всегда казалась магией. Что ж, отличная возможность узнать что-то новое. Я провёл день или два, пытаясь выяснить, какой механизм использовать для анализа аудиопотока. И в конце концов нашёл то что надо: это взаимная корреляция или кросс-корреляция (cross-correlation).
Octave
Обычно все ссылаются на реализацию MATLAB. Но MATLAB — дорогостоящее приложение, которое упрощает выполнение сложных математических операций, в том числе DSP. К счастью, есть бесплатная альтернатива под названием Octave. Кажется, в Octave несложно запустить взаимную корреляцию на двух аудиофайлах. Нужно лишь выполнить следующие команды:
pkg load signal
jingle = wavread('jingle.wav')(:,1);
audio = wavread ('audio.wav')(:,1);
[R, lag] = xcorr(jingle, audio);
plot(R);
Получится такой график:
Хорошо заметен пик, описывающий положение
jingle.wav
в audio.wav
. Что меня удивило, так это простота метода: всю работу делает xcorr()
, остальной код только для чтения файлов и отображения результата.Я хотел реализовать тот же алгоритм на Java, и тогда у меня будет инструмент, который:
- считывает аудиопоток со стандартного входа (например, от ffmpeg),
- анализирует его в поиске джинглов,
- выводит тот же поток на stdout и/или отключает его.
Использование stdin и stdout позволит подключить новый анализатор к другим приложениям, отвечающим за аудиотрансляцию и воспроизведение результата.
Чтение звуковых файлов
Первым делом Java-программа должна прочитать джингл (сохранённый в виде файла
.wav
) в массив. В файле есть некоторая дополнительная информацию вроде заголовков, метаданных и прочего, но нам нужен только звук. Подходящий формат называется PCM, это просто список чисел, представляющих звуки. Преобразовать WAV в PCM может ffmpeg:ffmpeg -i input.wav -f s16le -acodec pcm_s16le output.raw
Здесь каждый сэмпл сохраняется в виде 16-битного числа с обратным порядком байтов (little endian). В Java такое число называется
short
, а для автоматического преобразования входного потока в список значений short
можно использовать класс ByteBuffer
:ByteBuffer buf = ByteBuffer.allocate(4);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.put(bytes);
short leftChannel = buf.readShort(); // stereo stream
short rightChannel = buf.readShort();
Реверс-инжиниринг xcorr
Чтобы реализовать функцию
xcorr()
на Java, я изучил исходный код Octave. Не изменяя конечный результат, я смог заменить вызов xcorr() следующими строчками — их нужно переписать на Java:N = length(audio);
M = 2 ^ nextpow2(2 * N - 1);
pre = fft(postpad(prepad(jingle(:), length(jingle) + N - 1), M));
post = fft(postpad(audio(:), M));
cor = ifft(pre .* conj(post));
R = real(cor(1:2 * N));
Выглядит страшновато, но большинство функций — тривиальные операции с массивами. В основе кросс-корреляции лежит применение быстрого преобразования Фурье на звуковом образце.
Быстрое преобразование Фурье
Как человек, который не имел опыта работы с DSP, я просто рассматриваю FFT как функцию, которая берёт массив с описанием звукового образца — и возвращает массив с комплексными числами, представляющими частоты. Такой минималистичный подход хорошо сработал: я запустил реализацию FFT из пакета JTransforms и получил те же результаты, что в Octave. Я думаю, здесь отчасти карго-культ, но блин, это работает!
Запуск xcorr на потоке
Алгоритм выше предполагает, что
audio
представляет собой массив, в котором мы ищем jingle
. Это не совсем подходит для радиотрансляции, где у нас непрерывный поток звука. Чтобы запустить анализ, я создал циклический буфер чуть больше, чем продолжительность джингла, который нужно распознать. Входящий поток заполняет буфер, и как только он заполнен, запускается тест кросс-корреляции. Если ничего не найдено, то самая старая часть буфера отбрасывается — и снова ожидаем его заполнения.Я немного поэкспериментировал с длиной буфера и получил наилучшие результаты с размером буфера в 1,5 раза больше размера джингла.
Объединяем всё вместе
Получить поток в формате PCM несложно. Это можно сделать с помощью вышеупомянутого
ffmpeg
. Команда ниже перенаправляет поток на стандартный вход java
, а затем выводит Got jingle 0
или Got jingle 1
, когда в потоке найден соответствующий образец.ffmpeg -loglevel -8 -i http://stream3.polskieradio.pl:8904/\;stream -f s16le -acodec pcm_s16le - | java -jar target/analyzer-1.0.0-SNAPSHOT-jar-with-dependencies.jar 2 src/test/resources/commercial-start-44.1k.raw 500 src/test/resources/commercial-end-44.1k.raw 700
Автономная версия
Я также подготовил простую автономную версию анализатора, которая сама подключается к потоку «Тройки» (без внешнего
ffmpeg
) и воспроизводит результат с помощью javax.sound
. Всё вмещается в один файл JAR и содержит базовый пользовательский интерфейс с кнопками Star и Stop. Его можно скачать здесь. Если не любите запускать на своей машине чужие JAR (что совершенно правильно), то все исходники лежат на GitHub.Похоже, всё работает как надо :)
Дальнейшая работа
Конечная цель — отключить рекламу на уровне аппаратного усилителя, получая «реальный» FM-сигнал, а не некий интернет-поток. Об этом рассказано в следующей статье.
Обновление (июнь 2018)
Обсуждение на Hacker News
Обсуждение на Wykop
Обсуждение на Reddit
Комментарии (57)
Neuromantix
27.06.2018 19:28+4Хочу универсальный адблок в реалтайме по аудио и визуальным каналам.
SandroSmith
27.06.2018 20:08+3Black Mirror подсказывает, что это может быть плохой идеей
Neuromantix
27.06.2018 21:02+2Так с полным моим контролем, и полностью оффлайновый — никаких облаков и прочего. Обработка всего в носимой железке.
Konachan700
27.06.2018 21:06+4Очки антибезысходности. Вместо мусорной кучи дорисовывают жилище хоббитов, по луже во дворе плавают кораблики, на грязном месиве «газона» проходят гонки миниатюрных джипов, на серое небо накладываются красивые текстуры облаков, на месте промзоны рендерится море и острова… Эх, дождемся такого или нет…
immaculate
28.06.2018 03:41Такие очки существуют в голове у каждого человека, только пользоваться мало кто умеет. Все отрицательные и положительные эмоции приписываются картинке, получаемой от органов чувств, сознанием. Сама по себе лужа во дворе ни плохая, ни хорошая. Просто молекулы H2O на земле. Но если постоянно убеждать себя, что это просто невыносимо, что эта лужа мешает вам жить, то так оно и получится.
rustavelli
28.06.2018 23:45Лужа на асфальте — это дефект дорожного покрытия. Их там в принципе никогда быть не должно. Так что с официальной точки зрения, лужа — это однозначно плохо.
immaculate
29.06.2018 05:21Собственно, ваш комментарий является отличной иллюстрацией к тезису. «Официальная точка зрения» мало чем отличается от коллективной галлюцинации, если начать анализировать.
ru1z
28.06.2018 09:51Признаться, мне наушники помогают (особенно, если что-то интересное). Не знаю как это работает, но очень здорово переключают, особенно со скучно-рутинной действительности)
dim133
27.06.2018 20:12Если рекламные блоки действительно громкие, можно попробовать ловить начало рекламы по увеличению мощности сигнала.
port443
27.06.2018 20:53Там даже не сколько громкость, сколько компрессия как правило резко выше. Можно по этому признаку пытаться ловить.
vlreshet
28.06.2018 00:13Плохо в этом разбираюсь, но разве для того чтобы узнать уровень компрессии не надо иметь исходный файл + перекодированный (сжатый) файл? Сжатый у нас есть — радио, а оригинал?
port443
28.06.2018 00:32+1Я имел ввиду компрессию звука. Как раз это, мне кажется, средствами DSP определить не сложно.
huhen
27.06.2018 20:37На части радиостанций(как минимум у которых расчет на региональную ретрансляцию) в начале и конце рекламного блока идет специальная DTMF метка.
jukkagrao
27.06.2018 21:58Или секунда тишины, но для этого нужно иметь чистый сигнал, без рекламных вставок, а то открывающий код поймать получится, а закрывающий уже нет.
iig
28.06.2018 08:31Я читал, что длина рекламного блока на ТВ стандартная, или кратная стандартной. Чтобы без проблем вставлять местную рекламу. На радио не так?
Murimonai
27.06.2018 21:42Эм, то есть получается играет-играет нормальная музыка, все хорошо и потом резко становится тихо минут эдак на пять? Вот так задумывалось? Может лучше было не вырезать поток, а тушить ему громкость раза в два?
zigrus
28.06.2018 10:11я бы в этот блокировщик добавил и несколько песен, которые раздражают не хуже рекламы.
zxweed
28.06.2018 00:32+1вспоминается проект по подавлению тв-рекламы (чуваки заморочились и собрали базу актуального спама и сделали приставку, которая переключает каналы при поступлении сигнала по интернету) — так он разорился попросту из-за того, что «обычному человеку» (tm) на самом деле нравится смотреть рекламу, многие бы круглыми сутками совершенно добровольно смотрели рекламу стирального порошка типа «тогда мы идем к вам»
zigrus
28.06.2018 10:12у того проекта была проблема в позиционирование продукта
там что про про слежку за тем что смотрит телезритель…
mediamango
28.06.2018 10:12интересно, а неужели по DTMF-меткам не проще это было сделать? или они не везде используются?
Delsian
28.06.2018 12:43Проблема не только в рекламе. Радиостанции еще берут на работу ведущих-имбецилов, и приходится переключаться на другую станцию, как только после музыки начинаются их дебильные комментарии и гы-гы-гы. Не представляю, как такое можно отфильтровать.
dext63r
28.06.2018 12:58Нахожу плейлисты «музыка с радио ***»
Раньше в яндекс-радио подобная фишка была.
Жалко что радио-каналы нажаловались и подобную возможность выпилили.
cmd01
28.06.2018 14:43Есть интернет радиостанции. Реклама отключается что то за 1 евро в месяц. Мне нравится 1.fm это не реклама… просто для примера .
andersong
28.06.2018 13:13Насколько я помню, был проект по резке рекламы на ТВ, основанный на определении отображения значка телеканала в углу экрана (во время рекламы он не выводится), но его тоже зарубили.
besisland
28.06.2018 13:50Если не ошибаюсь, когда стали появляться такие приспособления для телевизоров, телеканалы просто стали делать не две заставки-маркера (начало и конец рекламного блока), а иногда три (кусочек заставки в середине блока), иногда две, иногда четыре.
DMGarikk
28.06.2018 15:57эти маркеры нужны для того чтобы правильно работало оборудование которое делает врезку местной рекламы на федеральных каналах
PavelMSTU
28.06.2018 20:09Давайте начистоту. Без понтов, но профессионал-датасаентист + хороший прогер (можно даже в одном лице) решат проблему рекламы с +99% точностью и +85% полнотой…
Вопрос: ПОЧЕМУ это до сих пор не сделали????iig
28.06.2018 23:33Потому что это не решение. Заменить рекламные вставки курсами английского можно. Только пользы от таких курсов, нарезанных роботом фрагментами по 40 секунд, будет меньше чем от рекламы.
vedenin1980
29.06.2018 00:03Можно включать любимые видео клипы, или вообще записывать канал и показывать с замедлением, скажем 20 минут. Тогда будет возможность не только рекламу вырезать, но постаить на паузу и сходить чай сделать.
P.S. На самом деле. есть подозрение. что мало кто хочет вырезать рекламу, так во время рекламных пауз занимается своими делами, то есть «вырезает ее и так в ручном режиме»
Kanut79
29.06.2018 09:31Потому что как показывает как минимум мой опыт это на самом деле мало кому нужно.
Есть куча людей которым реклама просто не мешает настолько чтобы они начали об этом задумываться и/или были бы готовы платить деньги за какой-то инструмент по «выпиливанию рекламы».
А для тех, кто готов потратить деньги чтобы от рекламы избавиться, есть просто другие варианты решения этой проблемы. Например платные источники контента, которые просто не используют рекламу.
iig
29.06.2018 00:11"включать любимые видео клипы"
Так себе решение. Смотришь футбол, или фильм… и тут… та-да-бумсь!
vedenin1980
29.06.2018 00:27Имел в виду музыкальные. Ну или смешные ролики с ютуба. Можно в начале и конце поставить свою заставку, чтобы та-да-бумсь не было. Как будто реклама не делает этот та-да-бумсь, особенно если рекламу вставляют неожиданно и с вкрученным звуком.
Alozar
Вот бы ещё Adblock для телевизора сделали… хотя я знаю его, он называется torrent
alexyr
Только надо искать торренты с надписью «без рекламы», а то достали всякие казино вставлять!
Alozar
вы забыли про регистрацию и смс
Lertmind
У нормальных студий озвучки (в основном сериалы) есть только две вставки аудио рекламы и присутствует оригинальная дорожка. Вычищают эту рекламу редко и не сразу. Если бы была программа, которая сравнивает дорожки и вставляет кусок оригинала на место рекламы, это бы всё упростило. Только нужен поиск не по известных вставкам, а по отсутствую голоса в оригинале.
Может уже есть готовое?
AfrinSoft
15 лет назад серийно выпускали телевизоры с функцией стоп-реклама. И это было в России.
www.nkj.ru/archive/articles/2815
moskva-televizor.ru/tv.php?buy=Rekord-37TTs-5173
После выпуска первой же партии в 20 тысяч телевизоров, разошедшейся как горячие пирожки, завод вместе с кб и патентами был стремительно выкуплен офшорным инвестором и тут же обанкрочен. В данный момент на бывшей территории александровского завода расположен торгово-развлекательный центр.
DMGarikk
очень я сомневаюсь что это произошло из-за стоп-рекламы
immaculate
Кто знает… Вот похожая история, тоже, кстати, из статьи в Науке и Жизни:
https://www.nkj.ru/archive/articles/10700/
DMGarikk
ну одно дело металлургия, где серьезная конкуренция на фоне монопольной структуры рынка, а другое какието телевизоры, где дешевле было бы заплатить за удаление этой функции чем покупать и банкротить завод с оборудованием которое проще выкинуть на свалку чем продать даже на металлолом
сдается мне что все эти старые советские заводы тупо не смогли перестроить производство в силу консерватизма, а как появилась возможность все это комуто сбагрить то этим и воспользовались… учитывая что конкурировать с китаем на этом рынке бесмысленно вообще, тут никакая антиреклама бы их не спасла
Kanut79
Как насчёт вот этого: www.telefairy.com?
mickvav
Оно не продается. Все ссылки на «Купить» — битые.
Kanut79
Она продаётся: www.fernsehfee.de/shop.html
Вот только поскольку телевизор здеь смотрят всё меньше народа и всё больше переходят на video on demand и streаm, то долго они скорее всего не протянут.
alsov
лет 10 назад был у меня ТВ-тюнер, в софте которого была возможность выреза рекламы. очень классная штука. гасила звук и затеняла экран.
алгоритм был простой и основан на том, что во время рекламы лого канала прячется.
в базе была куча разных лого + возможность подпихнуть свой.
а потом каналы лого начали делать полупрозрачными и перестали прятать…
DMGarikk
в некоторых блоков рекламы есть звуковая метка (для вставки региональных блоков), можно ориентироваться на нее… если ее отслеживать можно около 50% рекламы фильтровать
dext63r
Т.е. это уже было сильно раньше.
Интересно.
Javian
Сейчас не убирают логотип. В те времена был плагин для тюнеров Beholder