<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE article PUBLIC "-//NLM/DTD JATS (Z39.96) Journal Publishing DTD v1.2 20120330//EN" "http://jats.nlm.nih.gov/publishing/1.2/JATS-journalpublishing1.dtd">
    <!--<?xml-stylesheet type="text/xsl" href="article.xsl">-->
<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" article-type="research-article" dtd-version="1.2" xml:lang="en">
	<front>
		<journal-meta>
			<journal-id journal-id-type="issn">2303-9868</journal-id>
			<journal-id journal-id-type="eissn">2227-6017</journal-id>
			<journal-title-group>
				<journal-title>Международный научно-исследовательский журнал</journal-title>
			</journal-title-group>
			<issn pub-type="epub">2303-9868</issn>
			<publisher>
				<publisher-name>ООО Цифра</publisher-name>
			</publisher>
		</journal-meta>
		<article-meta>
			<article-id pub-id-type="doi">10.60797/IRJ.2026.169.17</article-id>
			<article-categories>
				<subj-group>
					<subject>Brief communication</subject>
				</subj-group>
			</article-categories>
			<title-group>
				<article-title>Программный комплекс для совмещения раздельно записанных видео- и аудиодорожек по артикуляции диктора</article-title>
			</title-group>
			<contrib-group>
				<contrib contrib-type="author" corresp="yes">
					<contrib-id contrib-id-type="orcid">https://orcid.org/0000-0001-9359-911X</contrib-id>
					<contrib-id contrib-id-type="rinc">https://elibrary.ru/author_profile.asp?id=830879</contrib-id>
					<contrib-id contrib-id-type="rid">https://publons.com/researcher/GLN-3042-2022</contrib-id>
					<name>
						<surname>Гибадуллин</surname>
						<given-names>Руслан Фаршатович</given-names>
					</name>
					<email>landwatersun@mail.ru</email>
					<xref ref-type="aff" rid="aff-1">1</xref>
				</contrib>
				<contrib contrib-type="author">
					<name>
						<surname>Шакирзянов</surname>
						<given-names>Марсель Эдуардович</given-names>
					</name>
					<email>morzik98@mail.ru</email>
					<xref ref-type="aff" rid="aff-1">1</xref>
				</contrib>
			</contrib-group>
			<aff id="aff-1">
				<label>1</label>
				<institution>Казанский национальный исследовательский технический университет им. А.Н. Туполева – КАИ</institution>
			</aff>
			<pub-date publication-format="electronic" date-type="pub" iso-8601-date="2026-07-17">
				<day>17</day>
				<month>07</month>
				<year>2026</year>
			</pub-date>
			<pub-date pub-type="collection">
				<year>2026</year>
			</pub-date>
			<volume>8</volume>
			<issue>169</issue>
			<fpage>1</fpage>
			<lpage>8</lpage>
			<history>
				<date date-type="received" iso-8601-date="2026-05-07">
					<day>07</day>
					<month>05</month>
					<year>2026</year>
				</date>
				<date date-type="accepted" iso-8601-date="2026-06-23">
					<day>23</day>
					<month>06</month>
					<year>2026</year>
				</date>
			</history>
			<permissions>
				<copyright-statement>Copyright: &amp;#x00A9; 2022 The Author(s)</copyright-statement>
				<copyright-year>2022</copyright-year>
				<license license-type="open-access" xlink:href="http://creativecommons.org/licenses/by/4.0/">
					<license-p>
						This is an open-access article distributed under the terms of the Creative Commons Attribution 4.0 International License (CC-BY 4.0), which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited. See 
						<uri xlink:href="http://creativecommons.org/licenses/by/4.0/">http://creativecommons.org/licenses/by/4.0/</uri>
					</license-p>
					.
				</license>
			</permissions>
			<self-uri xlink:href="https://research-journal.org/archive/7-169-2026-july/10.60797/IRJ.2026.169.17"/>
			<abstract>
				<p>Рассмотрены инженерные решения, лежащие в основе разработанного программного инструмента, который автоматически совмещает звуковую дорожку с видеорядом по движениям губ диктора. Инструмент написан на Python, имеет кроссплатформенную модульную организацию и использует ранее обученную свёрточно-темпоральную модель с контрастивной целевой функцией InfoNCE. Такая модель проецирует визуальный и акустический сигналы в единое векторное пространство. Сопоставление выполняется в два прохода. Сначала с шагом в 1 с пакетно строятся эмбеддинги для пятисекундных блоков, из которых формируется матрица косинусных сходств. Затем результат фильтруется: устраняются выбросы по медиане, контролируется монотонность аудиопозиций, а подряд идущие совпадения объединяются в общие сегменты. Пользователь может работать через окно на PyQt6 либо вызывать инструмент из терминала в пакетном режиме. Итоговый файл MP4 собирается с помощью утилиты FFmpeg. По итогам испытаний на 50 контрольных парах вида «короткий видеоролик — длинная звуковая запись» доля верно локализованных совпадений достигла 92,0 % при средней абсолютной погрешности начала корректно найденного отрезка 71 мс. Полный цикл обработки одной такой пары занимает 9,2 с при использовании видеокарты NVIDIA RTX 3060 и 37,7 с — на процессоре ноутбучного класса Intel Core i7.</p>
			</abstract>
			<kwd-group>
				<kwd>программный комплекс</kwd>
				<kwd> аудиовизуальная синхронизация</kwd>
				<kwd> артикуляция</kwd>
				<kwd> матрица косинусных сходств</kwd>
				<kwd> медианная фильтрация</kwd>
				<kwd> скользящее окно</kwd>
				<kwd> графический интерфейс</kwd>
				<kwd> FFmpeg</kwd>
				<kwd> PyQt6</kwd>
				<kwd> MediaPipe</kwd>
			</kwd-group>
		</article-meta>
	</front>
	<body>
		<sec>
			<title>HTML-content</title>
			<p>1. Введение</p>
			<p>Дистанция между обученной нейронной сетью и работающим инструментом синхронизации обычно оказывается значительно длиннее, чем принято считать. Сама модель способна переводить кадр области губ и фрагмент мел-спектрограммы в один и тот же эмбеддинг-вектор, однако конечному пользователю требуется не вектор, а собранный MP4-файл, в котором ранее записанная звуковая дорожка корректно совмещена с ранее снятым видео. Промежуток между этими двумя состояниями — прикладная задача со своей внутренней структурой. Она включает следующие этапы: подготовка входных потоков (приведение кадра к стандартному виду, выделение области губ, преобразование звука в мел-представление), посегментная обработка данных через сеть, аккуратное установление соответствия между полученными векторами, удаление выбросов, восстановление непрерывной временной оси, передача данных во внешний сборщик, наглядное отображение результата в интерфейсе. У каждого из перечисленных шагов имеются собственные инженерные нюансы, которые существенно сказываются как на качестве итога, так и на эксплуатационные характеристики всей системы </p>
			<p>[1]</p>
			<p>Подавляющее большинство публично доступных реализаций актуальных моделей аудиовизуальной синхронизации — SyncNet </p>
			<p>[2][3][4]</p>
			<p>Вторая существенная трудность связана со сменой постановки задачи. Вместо оценки одного смещения между двумя заведомо согласованными фрагментами требуется находить соответствия между коротким видеоотрывком и длинной аудиозаписью. Именно такой сценарий типичен для практики: у монтажёра обычно есть видеоклип длительностью 10–30-секунд (или несколько подобных клипов) и аудиозапись интервью либо подкаста продолжительностью в час и более. При этом нужно определить, в какой точке длинной записи находится фрагмент, содержательно соответствующий клипу. Простая модель, которая выдаёт для пары отрезков одно скалярное число, в этом случае непригодна. Необходимо построить отображение оси видеовремени в ось аудиовремени — оно должно отражать структуру всего материала.</p>
			<p>В представленной статье излагается архитектура и реализация программного комплекса, в котором обе указанные задачи решаются совместно. Используемая нейросетевая модель — свёрточно-темпоральная сеть, обученная с контрастивной функцией потерь InfoNCE, — подробно описана и обоснована в </p>
			<p>[5][6]</p>
			<p>2. Архитектура программного комплекса</p>
			<p>В качестве среды реализации выбран Python 3.10; комплекс выполнен в виде модульного кроссплатформенного приложения. Нейросетевые операции выполняет PyTorch, обработка видео опирается на связку OpenCV и MediaPipe, обработка аудио — на Librosa и soundfile, оконный интерфейс построен на PyQt6 (с интегрированным через Matplotlib просмотром графиков), а сборку итогового файла осуществляет внешний процесс FFmpeg. На этапе проектирования последовательно применялся ряд принципов, которые заранее задают общий облик кодовой базы и упрощают её последующее сопровождение </p>
			<p>[7]</p>
			<p>Функциональная декомпозиция. Кодовая база разбита на шесть функциональных подсистем: подготовка видеопотока, подготовка аудиопотока, синхронизация, обучение и оценка модели, графический интерфейс и сбор обучающих данных. Каждой подсистеме отведён собственный Python-пакет, и каждая решает строго одну задачу. Обмен данными между подсистемами организован через простые структуры — массивы NumPy, тензоры PyTorch и словари, описывающие результат.</p>
			<p>Централизованная конфигурация. Ключевые числовые параметры — разрешение области губ (96×96 пикселей), количество мел-фильтров (80), длительность блока грубого выравнивания (5 с), шаг скользящего окна (1 с), размер мини-пакета при инференсе (64 фрагмента), а также пороги постобработки — собраны в одном конфигурационном файле config.py. Такое решение существенно повышает воспроизводимость экспериментов и упрощает подбор настроек под конкретный сценарий применения.</p>
			<p>Двойной режим вычислений (CPU и GPU). Все компоненты, взаимодействующие с нейронной сетью, при запуске проверяют наличие CUDA-совместимого ускорителя: при его обнаружении задействуют GPU, при отсутствии — автоматически переходят на CPU. Эта возможность принципиально важна, поскольку среди потенциальных пользователей комплекса — не только обладатели рабочих станций с дискретной видеокартой, но и журналисты или монтажёры, работающие на обычном ноутбуке без выделенного GPU.</p>
			<p>Файловая иерархия комплекса спроектирована по принципу «одна папка — одна подсистема». Единая точка входа — модуль av_sync/main.py; режим работы выбирается первым позиционным аргументом командной строки: gui (открытие графического окна; используется по умолчанию, если аргументы отсутствуют), preprocess &lt;dir&gt; (пакетная подготовка указанного каталога с видеофайлами), train (запуск цикла обучения), evaluate (расчёт метрик на отложенной выборке), download &lt;url или поисковый запрос&gt; (загрузка одиночного видеоматериала по ссылке либо по запросу к видеохостингу), sync &lt;видео&gt; &lt;аудио&gt; [output] (синхронизация одной пары без графического интерфейса). Массовое наполнение датасета одной команды выполняет отдельный высокоуровневый скрипт download_training_data.py, описанный в разделе 6. Универсальность точки входа делает комплекс одинаково удобным как для интерактивной работы, так и для встраивания в автоматизированные конвейеры массовой обработки мультимедиа.</p>
			<p>Конвейер обработки в пользовательском режиме «синхронизация» устроен следующим образом. Подсистема подготовки видео принимает входной файл, в каждом кадре находит лицо с помощью MediaPipe FaceLandmarker, по 11 опорным точкам выделяет прямоугольную область губ, приводит её к фиксированному размеру 96×96 пикселей и складывает результат в трёхмерный массив формы </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mrow>
						<mml:mo stretchy="false">(</mml:mo>
						<mml:mi mathvariant="italic">T</mml:mi>
						<mml:mo mathvariant="italic">,</mml:mo>
						<mml:mn mathvariant="italic">96</mml:mn>
						<mml:mo mathvariant="italic">,</mml:mo>
						<mml:mn mathvariant="italic">96</mml:mn>
						<mml:mo stretchy="false">)</mml:mo>
					</mml:mrow>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>𝑇</mml:mi>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>Содержание задач каждой подсистемы и набор её ключевых внешних зависимостей представлены в таблице 1.</p>
			<table-wrap id="T1">
				<label>Table 1</label>
				<caption>
					<p>Подсистемы программного комплекса и набор их внешних зависимостей</p>
				</caption>
				<table>
					<tr>
						<td>Подсистема</td>
						<td>Функция</td>
						<td>Зависимости</td>
					</tr>
					<tr>
						<td>Предобработка видео</td>
						<td>Локализация лица, выделение области губ, нормализация</td>
						<td>OpenCV, MediaPipe</td>
					</tr>
					<tr>
						<td>Предобработка аудио</td>
						<td>Загрузка, ресэмплирование, вычисление мел-спектрограммы, сегментация</td>
						<td>Librosa, soundfile</td>
					</tr>
					<tr>
						<td>Синхронизация</td>
						<td>Пакетное вычисление эмбеддингов, матрица сходств, постобработка</td>
						<td>PyTorch, NumPy</td>
					</tr>
					<tr>
						<td>Обучение и оценка</td>
						<td>Цикл обучения, валидация, расчёт retrieval-метрик</td>
						<td>PyTorch, scikit-learn</td>
					</tr>
					<tr>
						<td>Графический интерфейс</td>
						<td>Главное окно, выбор файлов, прогресс, визуализация результата</td>
						<td>PyQt6, Matplotlib</td>
					</tr>
					<tr>
						<td>Сбор датасета</td>
						<td>Автоматическая загрузка обучающих видеоматериалов по запросам</td>
						<td>yt-dlp</td>
					</tr>
				</table>
			</table-wrap>
			<p> </p>
			<p>Принятая декомпозиция позволяет независимо развивать и проверять каждую подсистему в отрыве от остальных. Так, при появлении более точной нейросетевой модели достаточно заменить файл чекпоинта, не затрагивая остальной код. Чтобы добавить поддержку нового видеоформата, требуется доработать только подсистему подготовки видео. Графический интерфейс отделён от вычислительной части и при необходимости может быть заменён на веб-фронтенд либо встроен в стороннее приложение для видеомонтажа.</p>
			<p>3. Подсистема предобработки данных</p>
			<p>Поступающий видеопоток обслуживает класс </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mrow>
						<mml:mi mathvariant="italic">V</mml:mi>
						<mml:mi mathvariant="italic">i</mml:mi>
						<mml:mi mathvariant="italic">d</mml:mi>
						<mml:mi mathvariant="italic">e</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">P</mml:mi>
						<mml:mi mathvariant="italic">r</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">c</mml:mi>
						<mml:mi mathvariant="italic">e</mml:mi>
						<mml:mi mathvariant="italic">s</mml:mi>
						<mml:mi mathvariant="italic">s</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">r</mml:mi>
					</mml:mrow>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mrow>
						<mml:mo stretchy="false">(</mml:mo>
						<mml:mi mathvariant="italic">T</mml:mi>
						<mml:mo mathvariant="italic">,</mml:mo>
						<mml:mn mathvariant="italic">96</mml:mn>
						<mml:mo mathvariant="italic">,</mml:mo>
						<mml:mn mathvariant="italic">96</mml:mn>
						<mml:mo stretchy="false">)</mml:mo>
					</mml:mrow>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>𝑇</mml:mi>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>Локализацию лица обеспечивает MediaPipe FaceLandmarker </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:msub>
						<mml:mover>
							<mml:mrow>
								<mml:mi>x</mml:mi>
							</mml:mrow>
							<mml:mo stretchy="false">^</mml:mo>
						</mml:mover>
						<mml:mrow>
							<mml:mi>t</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mo>=</mml:mo>
					<mml:mn>0</mml:mn>
					<mml:mo>,</mml:mo>
					<mml:mn>7</mml:mn>
					<mml:mi>·</mml:mi>
					<mml:msub>
						<mml:mi>x</mml:mi>
						<mml:mrow>
							<mml:mi>t</mml:mi>
							<mml:mo>−</mml:mo>
							<mml:mn>1</mml:mn>
						</mml:mrow>
					</mml:msub>
					<mml:mo>+</mml:mo>
					<mml:mn>0</mml:mn>
					<mml:mo>,</mml:mo>
					<mml:mn>3</mml:mn>
					<mml:mi>·</mml:mi>
					<mml:msub>
						<mml:mi>x</mml:mi>
						<mml:mrow>
							<mml:mi>t</mml:mi>
						</mml:mrow>
					</mml:msub>
				</mml:mrow>
			</mml:math>
			<p>[8]</p>
			<p>Если детектор не обнаружил лица в очередном кадре (например, говорящий отвернулся или сцена содержит только крупный план без лица), используется последний валидный ограничивающий прямоугольник. Если лицо отсутствует в нескольких подряд идущих кадрах, текущий кадр заполняется нулями и помечается флагом «невалидный». При последующей синхронизации такие кадры исключаются из вычислений: их вклад в эмбеддинг блока обнуляется, а веса при усреднении соответствующим образом перенормируются.</p>
			<p>Класс </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mrow>
						<mml:mi mathvariant="italic">A</mml:mi>
						<mml:mi mathvariant="italic">u</mml:mi>
						<mml:mi mathvariant="italic">d</mml:mi>
						<mml:mi mathvariant="italic">i</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">P</mml:mi>
						<mml:mi mathvariant="italic">r</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">c</mml:mi>
						<mml:mi mathvariant="italic">e</mml:mi>
						<mml:mi mathvariant="italic">s</mml:mi>
						<mml:mi mathvariant="italic">s</mml:mi>
						<mml:mi mathvariant="italic">o</mml:mi>
						<mml:mi mathvariant="italic">r</mml:mi>
					</mml:mrow>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>Такое жёсткое временно́е соответствие между видео- и аудиоканалами — обязательное требование архитектуры сети: совместное эмбеддинг-пространство построено в предположении, что каждый видеокадр сопоставлен акустическому сегменту равной длительности. Любое нарушение этого баланса, в частности отклонение реальной частоты кадров входного видео от номинальной, ведёт к деградации синхронизации. Поэтому при неоднозначном fps подсистема подготовки видео выводит соответствующее диагностическое сообщение и приводит частоту кадров к 25 Гц линейной интерполяцией. Согласованная с ней подсистема подготовки аудио оперирует уже корректным потоком кадров.</p>
			<p>4. Двухступенчатый алгоритм сопоставления</p>
			<p>Пусть </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>V</mml:mi>
					<mml:mo>=</mml:mo>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:msub>
						<mml:mi>V</mml:mi>
						<mml:mn>1</mml:mn>
					</mml:msub>
					<mml:mo>,</mml:mo>
					<mml:mo>…</mml:mo>
					<mml:mo>,</mml:mo>
					<mml:msub>
						<mml:mi>V</mml:mi>
						<mml:mrow>
							<mml:msub>
								<mml:mi>T</mml:mi>
								<mml:mi>V</mml:mi>
							</mml:msub>
						</mml:mrow>
					</mml:msub>
					<mml:mo stretchy="false">)</mml:mo>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>T</mml:mi>
						<mml:mi>V</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>A</mml:mi>
					<mml:mo>=</mml:mo>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:msub>
						<mml:mi>A</mml:mi>
						<mml:mn>1</mml:mn>
					</mml:msub>
					<mml:mo>,</mml:mo>
					<mml:mo>…</mml:mo>
					<mml:mo>,</mml:mo>
					<mml:msub>
						<mml:mi>A</mml:mi>
						<mml:mrow>
							<mml:msub>
								<mml:mi>T</mml:mi>
								<mml:mi>A</mml:mi>
							</mml:msub>
						</mml:mrow>
					</mml:msub>
					<mml:mo stretchy="false">)</mml:mo>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>T</mml:mi>
						<mml:mi>A</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>T</mml:mi>
						<mml:mi>V</mml:mi>
					</mml:msub>
					<mml:mo>≪</mml:mo>
					<mml:msub>
						<mml:mi>T</mml:mi>
						<mml:mi>A</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mo stretchy="false">{</mml:mo>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:msub>
						<mml:mi>α</mml:mi>
						<mml:mi>i</mml:mi>
					</mml:msub>
					<mml:mo>,</mml:mo>
					<mml:msub>
						<mml:mi>β</mml:mi>
						<mml:mi>i</mml:mi>
					</mml:msub>
					<mml:mo stretchy="false">]</mml:mo>
					<mml:mi>·</mml:mi>
					<mml:mo stretchy="false">[</mml:mo>
					<mml:msub>
						<mml:mi>γ</mml:mi>
						<mml:mi>i</mml:mi>
					</mml:msub>
					<mml:mo>,</mml:mo>
					<mml:msub>
						<mml:mi>δ</mml:mi>
						<mml:mi>i</mml:mi>
					</mml:msub>
					<mml:mo stretchy="false">]</mml:mo>
					<mml:msubsup>
						<mml:mo stretchy="false">}</mml:mo>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mo>=</mml:mo>
							<mml:mn>1</mml:mn>
						</mml:mrow>
						<mml:mi>K</mml:mi>
					</mml:msubsup>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>На грубом этапе и видеоряд, и спектрограмма нарезаются на перекрывающиеся блоки длительностью 5 с (125 кадров) со сдвигом в 1 с (25 кадров). Для каждого блока пакетно рассчитывается эмбеддинг соответствующей модальности с помощью обученных энкодеров </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>E</mml:mi>
						<mml:mrow>
							<mml:mi>v</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>E</mml:mi>
						<mml:mi>a</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>Пусть </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>N</mml:mi>
						<mml:mi>V</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>N</mml:mi>
						<mml:mi>A</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mover>
						<mml:mrow>
							<mml:mi>V</mml:mi>
						</mml:mrow>
						<mml:mo stretchy="false">^</mml:mo>
					</mml:mover>
					<mml:mo>∈</mml:mo>
					<mml:msup>
						<mml:mi>ℝ</mml:mi>
						<mml:mrow>
							<mml:msub>
								<mml:mi>N</mml:mi>
								<mml:mi>V</mml:mi>
							</mml:msub>
							<mml:mi>×</mml:mi>
							<mml:mi>d</mml:mi>
						</mml:mrow>
					</mml:msup>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mover>
						<mml:mrow>
							<mml:mi>A</mml:mi>
						</mml:mrow>
						<mml:mo stretchy="false">^</mml:mo>
					</mml:mover>
					<mml:mo>∈</mml:mo>
					<mml:msup>
						<mml:mi>ℝ</mml:mi>
						<mml:mrow>
							<mml:msub>
								<mml:mi>N</mml:mi>
								<mml:mi>A</mml:mi>
							</mml:msub>
							<mml:mi>×</mml:mi>
							<mml:mi>d</mml:mi>
						</mml:mrow>
					</mml:msup>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>𝑑</mml:mi>
					<mml:mo>=</mml:mo>
					<mml:mn>256</mml:mn>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>S</mml:mi>
					<mml:mo>=</mml:mo>
					<mml:mover>
						<mml:mrow>
							<mml:mi>V</mml:mi>
						</mml:mrow>
						<mml:mo stretchy="false">^</mml:mo>
					</mml:mover>
					<mml:mi>·</mml:mi>
					<mml:msup>
						<mml:mover>
							<mml:mrow>
								<mml:mi>A</mml:mi>
							</mml:mrow>
							<mml:mo stretchy="false">^</mml:mo>
						</mml:mover>
						<mml:mrow>
							<mml:mi>·</mml:mi>
						</mml:mrow>
					</mml:msup>
					<mml:mo>∈</mml:mo>
					<mml:msup>
						<mml:mi>ℝ</mml:mi>
						<mml:mrow>
							<mml:msub>
								<mml:mi>N</mml:mi>
								<mml:mi>V</mml:mi>
							</mml:msub>
							<mml:mi>×</mml:mi>
							<mml:msub>
								<mml:mi>N</mml:mi>
								<mml:mi>A</mml:mi>
							</mml:msub>
						</mml:mrow>
					</mml:msup>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p> </p>
			<p>В матрице каждая строка соответствует отдельному видеоблоку, а каждый столбец — отдельному аудиоблоку. Элемент </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>S</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mi>j</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:msup>
						<mml:mi>j</mml:mi>
						<mml:mrow>
							<mml:mo>*</mml:mo>
						</mml:mrow>
					</mml:msup>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:mi>i</mml:mi>
					<mml:mo stretchy="false">)</mml:mo>
					<mml:mo>=</mml:mo>
					<mml:munder>
						<mml:mrow>
							<mml:mo>argmax</mml:mo>
						</mml:mrow>
						<mml:mrow>
							<mml:mi>j</mml:mi>
							<mml:mo>∈</mml:mo>
							<mml:mrow>
								<mml:mo stretchy="true" fence="true" form="prefix">[</mml:mo>
								<mml:mn>1</mml:mn>
								<mml:mo>,</mml:mo>
								<mml:msub>
									<mml:mi>N</mml:mi>
									<mml:mrow>
										<mml:mi>A</mml:mi>
									</mml:mrow>
								</mml:msub>
								<mml:mo stretchy="true" fence="true" form="postfix">]</mml:mo>
							</mml:mrow>
						</mml:mrow>
					</mml:munder>
					<mml:msub>
						<mml:mi>S</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mi>j</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mo>,</mml:mo>
					<mml:mspace width="1em"/>
					<mml:msub>
						<mml:mi>c</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mo>=</mml:mo>
					<mml:msub>
						<mml:mi>S</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mo>,</mml:mo>
							<mml:msup>
								<mml:mi>j</mml:mi>
								<mml:mrow>
									<mml:mo>*</mml:mo>
								</mml:mrow>
							</mml:msup>
							<mml:mo stretchy="false">(</mml:mo>
							<mml:mi>i</mml:mi>
							<mml:mo stretchy="false">)</mml:mo>
						</mml:mrow>
					</mml:msub>
				</mml:mrow>
			</mml:math>
			<p>где </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msup>
						<mml:mi>j</mml:mi>
						<mml:mo>*</mml:mo>
					</mml:msup>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:mi>i</mml:mi>
					<mml:mo stretchy="false">)</mml:mo>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mi>𝑖</mml:mi>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>𝑐</mml:mi>
						<mml:mrow>
							<mml:mi>𝑖</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:msub>
						<mml:mi>N</mml:mi>
						<mml:mi>V</mml:mi>
					</mml:msub>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<p>Выбор шага скользящего окна в 1 секунду является компромиссным. Уменьшение шага обеспечивает более плотное покрытие, но пропорционально увеличивает количество прогонов через сеть и общее время обработки. Увеличение шага, наоборот, ускоряет вычисления, однако повышает риск пропустить точную точку совпадения. На тестовой подвыборке при шаге в 1 с алгоритм корректно отыскивает совпадение в 92,0% случаев; при шаге в 2 с этот показатель падает до 88,4%, а при шаге в 0,5 с возрастает лишь до 92,8%, что не окупает почти двукратного замедления. Размер мини-пакета (64 блока) подобран таким образом, чтобы загрузить вычислительные ресурсы GPU NVIDIA RTX 3060 и при этом удерживать пиковое потребление видеопамяти в пределах 4 ГБ. </p>
			<p>Грубый этап возвращает по одному кандидату на каждый видеоблок, и среди них неизбежно встречаются ошибочные — например, фрагменты с тишиной, короткими речевыми паузами или невнятной артикуляцией. Использовать такой результат без дополнительной обработки невозможно: в нём могут попадаться отдельные «выбросы», когда несколько соседних видеоблоков получили совпадения в близких аудиопозициях, а один — в семантически не связанной точке записи.</p>
			<p>Очистка совпадений выполняется методом </p>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mi>$</mml:mi>
					<mml:mrow>
						<mml:mi mathvariant="italic">_</mml:mi>
						<mml:mi mathvariant="italic">b</mml:mi>
						<mml:mi mathvariant="italic">u</mml:mi>
						<mml:mi mathvariant="italic">i</mml:mi>
						<mml:mi mathvariant="italic">l</mml:mi>
						<mml:mi mathvariant="italic">d</mml:mi>
						<mml:mi mathvariant="italic">_</mml:mi>
						<mml:mi mathvariant="italic">t</mml:mi>
						<mml:mi mathvariant="italic">i</mml:mi>
						<mml:mi mathvariant="italic">m</mml:mi>
						<mml:mi mathvariant="italic">e</mml:mi>
						<mml:mi mathvariant="italic">l</mml:mi>
						<mml:mi mathvariant="italic">i</mml:mi>
						<mml:mi mathvariant="italic">n</mml:mi>
						<mml:mi mathvariant="italic">e</mml:mi>
					</mml:mrow>
					<mml:mi>$</mml:mi>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:msubsup>
						<mml:mrow>
							<mml:mo stretchy="true" fence="true" form="prefix">(</mml:mo>
							<mml:msub>
								<mml:mi>γ</mml:mi>
								<mml:mrow>
									<mml:mi>i</mml:mi>
								</mml:mrow>
							</mml:msub>
							<mml:mo stretchy="true" fence="true" form="postfix">)</mml:mo>
						</mml:mrow>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mo>=</mml:mo>
							<mml:mn>1</mml:mn>
						</mml:mrow>
						<mml:mrow>
							<mml:msub>
								<mml:mi>N</mml:mi>
								<mml:mrow>
									<mml:mi>V</mml:mi>
								</mml:mrow>
							</mml:msub>
						</mml:mrow>
					</mml:msubsup>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:mo stretchy="false">(</mml:mo>
					<mml:mi>i</mml:mi>
					<mml:mo>−</mml:mo>
					<mml:mn>1</mml:mn>
					<mml:mo>,</mml:mo>
					<mml:mi>i</mml:mi>
					<mml:mo stretchy="false">)</mml:mo>
				</mml:mrow>
			</mml:math>
			<mml:math display="inline">
				<mml:mrow>
					<mml:msub>
						<mml:mi>γ</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
						</mml:mrow>
					</mml:msub>
					<mml:mo>≥</mml:mo>
					<mml:msub>
						<mml:mi>γ</mml:mi>
						<mml:mrow>
							<mml:mi>i</mml:mi>
							<mml:mo>−</mml:mo>
							<mml:mn>1</mml:mn>
						</mml:mrow>
					</mml:msub>
				</mml:mrow>
			</mml:math>
			<p>Каждому полученному сегменту приписывается средний уровень уверенности по всем входящим в него совпадениям; впоследствии это число используется при сортировке выдачи. Сегменты с уверенностью ниже эмпирически подобранного порога 0,3 по умолчанию сопровождаются предупреждением: модель в их корректности не уверена, и пользователю желательно проверить такой результат вручную.</p>
			<p>Точность работы двухступенчатого алгоритма проверялась на тестовой подвыборке из 50 пар вида «короткое видео — длинная аудиозапись». В каждой паре видеоматериал представлял собой фрагмент длительностью от 10 до 30 секунд, выделенный из записей, не пересекающихся с обучающей частью датасета. Аудиоматериал — полная запись, охватывающая этот фрагмент, с длительностью от 10 до 60 минут. Используемые метрики и их значения представлены в таблице 2.</p>
			<table-wrap id="T2">
				<label>Table 2</label>
				<caption>
					<p>Показатели качества двухступенчатого алгоритма на тестовой подвыборке из 50 пар</p>
				</caption>
				<table>
					<tr>
						<td>Метрика</td>
						<td>Значение</td>
					</tr>
					<tr>
						<td>Доля правильно найденных совпадений, %</td>
						<td>92,0</td>
					</tr>
					<tr>
						<td>Средняя абсолютная ошибка начала сегмента, мс</td>
						<td>71</td>
					</tr>
					<tr>
						<td>Медианная абсолютная ошибка, мс</td>
						<td>44</td>
					</tr>
					<tr>
						<td>Доля случаев с ошибкой начала &lt; 100 мс, %</td>
						<td>78,0</td>
					</tr>
					<tr>
						<td>Доля грубых ошибок (&gt;1 с или неверный сегмент), %</td>
						<td>8,0</td>
					</tr>
				</table>
			</table-wrap>
			<p> </p>
			<p>Цифры 92,0% верно отыскиваемых совпадений и 71 мс средней абсолютной погрешности по началу корректного сегмента отвечают уровню, готовому к серьёзной эксплуатации. В большинстве сюжетов видеоредактору достаточно просто принять предлагаемый результат, тогда как для 8% трудных случаев низкая уверенность модели сразу подсвечивает необходимость ручного контроля. Промежуточная категория — примерно 14% пар — попадает в диапазон погрешности в 0,1–1,0 с. Здесь, как правило, достаточно слегка скорректировать границы вручную. Все зафиксированные грубые сбои (та самая доля в 8%) приходятся на ролики с откровенно низким качеством записи, заметным фоновым шумом и одновременным присутствием в кадре нескольких говорящих — то есть на условия, в которых модель не тренировалась.</p>
			<p>5. Подсистема автоматизированного сбора датасета</p>
			<p>Качественное обучение нейросети невозможно без репрезентативной коллекции видеозаписей с крупным планом лица говорящего </p>
			<p>[9][10][11][12]</p>
			<p>Высокоуровневая логика массового сбора реализована в отдельном скрипте download_training_data.py. Он обрабатывает заранее подготовленный список из 40 англоязычных поисковых запросов, охватывающих разнообразные сюжеты с одиночным говорящим: интервью, подкасты, лекции, обучающие материалы и обзоры. Для каждого запроса скрипт скачивает по три ролика. Между запросами выдерживается пятиминутная пауза — это снижает вероятность временной блокировки со стороны видеохостинга. Перед каждым новым запросом проверяется объём свободного места на диске: если он падает ниже 30 ГБ скрипт аккуратно завершает работу, сохраняя всё ранее загруженные файлы. Состав запросов специально подобран так, чтобы обеспечить вариативность условий съёмки, ракурсов, освещения, голосов и тем — без этого обучаемая модель не получит достаточной обобщающей способности.</p>
			<p>Когда загрузка завершена, скачанные ролики проходят пакетную предобработку, которую запускает команда python -m av_sync.main preprocess &lt;video_dir&gt;. В ходе предобработки формируются серии кадров с губами, рассчитываются мел-спектрограммы, которые затем нарезаются под видеокадры. Итог записывается на диск в формате .npy с поддержкой memory-mapping. Такая схема хранения избавляет от необходимости держать весь датасет в RAM при дальнейшей работе. Файлы, прошедшие обработку ранее, пропускаются автоматически — это даёт возможность инкрементально дополнять корпус новыми записями. Если обработка отдельного ролика срывается (например, видеоконтейнер повреждён либо в кадрах не нашлось лица), скрипт пишет об этом в журнал и переходит к следующему файлу, не останавливая обработку остальных.</p>
			<p>6. Интерфейсы пользователя</p>
			<p>Оконный интерфейс реализован на PyQt6 — официальной привязке Python к фреймворку Qt 6, который давно стал отраслевым стандартом для кроссплатформенных настольных приложений. Главное окно поделено на четыре функциональные зоны: панель выбора входных файлов (видео и аудио — через системные диалоги открытия файлов), панель прогресса с указанием текущей стадии обработки, область визуализации полученного результата и панель управления экспортом.</p>
			<p>Визуальная зона ответа включает два связанных компонента: тепловую карту, которая отрисовывает матрицу косинусных сходств, и табличный перечень обнаруженных сегментов. Тепловую карту строит Matplotlib </p>
			<p>[13]</p>
			<p>Ресурсоёмкие стадии обработки — подготовка видео, инференс сети и сборка итогового файла — вынесены в отдельный QThread, что предотвращает «зависание» основного потока GUI. Прогресс передаётся в главное окно посредством механизма сигналов Qt и отображается в виде процентной шкалы с подписью текущего этапа. При прерывании операции пользователем (нажатии кнопки «Отмена») во внутреннем потоке устанавливается флаг отмены, который регулярно проверяется во всех длительных циклах подсистем. Благодаря этому циклы корректно завершают работу и освобождают захваченные ресурсы.</p>
			<p>Для удобства встраивания инструмента в автоматизированные конвейеры, предусмотрен запуск без графической оболочки. Весь цикл обработки поднимается одной командой python -m av_sync.main sync video.mp4 audio.wav output.mp4. На выходе сохраняется готовый файл по указанному пути, а в стандартный вывод поступают журнал работы и числовые показатели качества в формате JSON, что упрощает их подхват внешними инструментами. Стандартный код выхода (нулевой при удаче, иной — при ошибке) делает инструмент совместимым со скриптовыми оболочками Bash и PowerShell, утилитой Make и привычными системами непрерывной интеграции.</p>
			<p>7. Эксплуатационные характеристики</p>
			<p>Замеры производительности проводились на трёх показательных конфигурациях: рабочей станции с GPU NVIDIA RTX 3060, ноутбуке с процессором Intel Core i7-12700H без отдельного графического ускорителя и облачной виртуальной машине с 4 vCPU. Тестовая нагрузка во всех случаях была одна и та же — пара «видеоклип длиной 10 с в 720p плюс 15-минутная звуковая запись». На каждой конфигурации фиксировались две величины: полное время прохода и пик потребления памяти. Сводка результатов представлена в таблице 3.</p>
			<table-wrap id="T3">
				<label>Table 3</label>
				<caption>
					<p>Время обработки одной пары для различных пользовательских конфигураций</p>
				</caption>
				<table>
					<tr>
						<td>Этап</td>
						<td>RTX 3060 (GPU)</td>
						<td>Intel i7 (CPU)</td>
						<td>VM 4 vCPU</td>
					</tr>
					<tr>
						<td>Предобработка видео, с</td>
						<td>3,2</td>
						<td>3,5</td>
						<td>4,1</td>
					</tr>
					<tr>
						<td>Предобработка аудио, с</td>
						<td>1,8</td>
						<td>2,1</td>
						<td>2,4</td>
					</tr>
					<tr>
						<td>Инференс сети, с</td>
						<td>1,4</td>
						<td>23,8</td>
						<td>47,2</td>
					</tr>
					<tr>
						<td>Постобработка матчей, с</td>
						<td>0,2</td>
						<td>0,2</td>
						<td>0,3</td>
					</tr>
					<tr>
						<td>Сборка MP4 (FFmpeg), с</td>
						<td>2,6</td>
						<td>8,1</td>
						<td>12,7</td>
					</tr>
					<tr>
						<td>Полное время, с</td>
						<td>9,2</td>
						<td>37,7</td>
						<td>66,7</td>
					</tr>
					<tr>
						<td>Пик ОЗУ, ГБ</td>
						<td>2,1</td>
						<td>2,3</td>
						<td>2,5</td>
					</tr>
					<tr>
						<td>Пик видеопамяти, ГБ</td>
						<td>3,4</td>
						<td>–</td>
						<td>–</td>
					</tr>
				</table>
			</table-wrap>
			<p> </p>
			<p>При использовании отдельной видеокарты NVIDIA RTX 3060 полный проход одной пары укладывается в 9,2 с. При этом непосредственно прогон через сеть отнимает порядка 1,4 с, а основная часть времени уходит на подготовительные стадии и финальную сборку. Если же расчёт выполняется исключительно на CPU ноутбука Intel Core i7-12700H, то общее время вырастает до 37,7 с. Примерно 24 с из них тратятся на инференс: здесь даёт себя знать отсутствие того массового параллелизма по блокам, который GPU обеспечивает «бесплатно». В сценарии облачной виртуальной машины с 4 vCPU время обработки увеличивается до 66,7 с — это самый медленный из проверенных режимов, однако и в нём инструмент остаётся работоспособным. Что касается потребления памяти, верхняя планка ОЗУ во всех трёх замерах не превышает 2,5 ГБ. Диапазон 2,1–2,5 ГБ обусловлен разной кэш-стратегией с GPU и без него. Пиковое потребление видеопамяти остаётся в пределах 3,4 ГБ — такие требования вполне посильны даже для бюджетных потребительских ускорителей.</p>
			<p>8. Заключение</p>
			<p>В настоящей статье изложены архитектура и двухступенчатый алгоритм сопоставления, образующие основу программного комплекса автоматической синхронизации аудио- и видеопотоков по артикуляции говорящего. Сформулируем главные итоги.</p>
			<p>1. Построена модульная архитектура комплекса, объединяющая шесть функциональных подсистем — подготовку видео, подготовку аудио, собственно синхронизацию, обучение и оценку, графический интерфейс и сбор обучающих данных, — которые связаны простыми типами данных и общим конфигурационным модулем. Принятая архитектура одинаково поддерживает работу как через оконный интерфейс, так и в пакетном режиме из командной строки и не требует изменения исходного кода при переключении между CPU и GPU.</p>
			<p>2. Разработан и реализован двухступенчатый алгоритм сопоставления. Грубый этап выполняет пакетный расчёт эмбеддингов для пятисекундных блоков и собирает матрицу косинусных сходств. Этап постобработки включает медианную фильтрацию аудиопозиций, проверку их монотонности с интерполяционной заменой выбросов и слияние смежных совпадений в непрерывные сегменты. На тестовой подвыборке из 50 пар «короткое видео — длинная аудиозапись» алгоритм корректно локализует совпадение в 92,0% случаев со средней абсолютной ошибкой начала корректно найденного сегмента 71 мс.</p>
			<p>3. Эксплуатационные испытания, проведённые в трёх характерных средах, дали следующие показатели: полный проход одной пары занимает 9,2 с при наличии массовой видеокарты и 37,7 с на CPU обыкновенного ноутбука; верхний предел по оперативной памяти ограничен 2,5 ГБ, по видеопамяти — 3,4 ГБ. Такая комбинация скорости и скромного потребления ресурсов делает разработанный инструмент пригодным для тех ниш, в которых громоздкие исследовательские реализации SyncNet, Wav2Lip и им подобные просто не работают: для повседневной работы журналистов и видеомонтажёров на личных машинах, для архивных учреждений, для дешёвых виртуальных серверов общедоступных хостингов.</p>
			<p>Дальнейшее развитие комплекса видится в нескольких направлениях. Во-первых, обработка кадров, в которых одновременно говорят несколько человек. Во-вторых, добавление онлайн-режима, позволяющего синхронизировать потоки по мере их поступления, — это важно для систем видеоконференций. В-третьих, подключение к популярным редакторам нелинейного видеомонтажа через плагины.</p>
		</sec>
		<sec sec-type="supplementary-material">
			<title>Additional File</title>
			<p>The additional file for this article can be found as follows:</p>
			<supplementary-material xmlns:xlink="http://www.w3.org/1999/xlink" id="S1" xlink:href="https://doi.org/10.5334/cpsy.78.s1">
				<!--[<inline-supplementary-material xlink:title="local_file" xlink:href="https://research-journal.org/media/articles/25399.docx">25399.docx</inline-supplementary-material>]-->
				<!--[<inline-supplementary-material xlink:title="local_file" xlink:href="https://research-journal.org/media/articles/25399.pdf">25399.pdf</inline-supplementary-material>]-->
				<label>Online Supplementary Material</label>
				<caption>
					<p>
						Further description of analytic pipeline and patient demographic information. DOI:
						<italic>
							<uri>https://doi.org/10.60797/IRJ.2026.169.17</uri>
						</italic>
					</p>
				</caption>
			</supplementary-material>
		</sec>
	</body>
	<back>
		<ack>
			<title>Acknowledgements</title>
			<p/>
		</ack>
		<sec>
			<title>Competing Interests</title>
			<p/>
		</sec>
		<ref-list>
			<ref id="B1">
				<label>1</label>
				<mixed-citation publication-type="confproc">Корнеев В.В. Специализированные аппаратные нейросетевые ускорители / В.В. Корнеев // Программная инженерия. — 2023. — Т. 14, № 1. — С. 3–11. — DOI: 10.17587/prin.14.3-11.</mixed-citation>
			</ref>
			<ref id="B2">
				<label>2</label>
				<mixed-citation publication-type="confproc">Roy A. SyncNet: Harmonizing Nodes for Efficient Learning / A. Roy, B.S. Gyanchandani, J. Sahu [et al.] // 2024 International Conference on Software, Telecommunications and Computer Networks (SoftCOM). — Split, Croatia, 2024. — P. 1–6. — DOI: 10.23919/SoftCOM62040.2024.10721994.</mixed-citation>
			</ref>
			<ref id="B3">
				<label>3</label>
				<mixed-citation publication-type="confproc">Xueming Q. Design and Implementation of a Wav2Lip-based Digital Human Framework for Intelligent Power Customer Service / Q. Xueming [et al.] // 2025 IEEE 3rd International Conference on Electrical, Automation and Computer Engineering (ICEACE). — Changchun, China, 2025. — P. 892–896. — DOI: 10.1109/ICEACE67491.2025.11439472.</mixed-citation>
			</ref>
			<ref id="B4">
				<label>4</label>
				<mixed-citation publication-type="confproc">Virkkunen A. Investigating the Clusters Discovered By Pre-Trained AV-HuBERT / A. Virkkunen, M. Sarvaš, G. Huang [et al.] // ICASSP 2024 — 2024 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). — Seoul, Republic of Korea, 2024. — P. 11196–11200. — DOI: 10.1109/ICASSP48485.2024.10447434.</mixed-citation>
			</ref>
			<ref id="B5">
				<label>5</label>
				<mixed-citation publication-type="confproc">Long Y. Enhancing Educational Content Matching Using Transformer Models and InfoNCE Loss / Y. Long, D. Gu, X. Li [et al.] // 2024 IEEE 7th International Conference on Information Systems and Computer Aided Education (ICISCAE). — Dalian, China, 2024. — P. 11–15. — DOI: 10.1109/ICISCAE62304.2024.10761438.</mixed-citation>
			</ref>
			<ref id="B6">
				<label>6</label>
				<mixed-citation publication-type="confproc">Lei X. Design and Implementation of a Real-Time Video Stream Analysis System Based on FFMPEG / X. Lei, X. Jiang, C. Wang // 2013 Fourth World Congress on Software Engineering. — Hong Kong, China, 2013. — P. 212–216. — DOI: 10.1109/WCSE.2013.38.</mixed-citation>
			</ref>
			<ref id="B7">
				<label>7</label>
				<mixed-citation publication-type="confproc">Куликов Р.И. Информационная система на основе нейросети для автоматической генерации субтитров к видео / Р.И. Куликов // Профессиональные коммуникации в научной среде — фактор обеспечения качества исследований : материалы XIII Всерос. науч.-практ. конф., Альметьевск, 16 апреля 2024 г. — Санкт-Петербург : ООО Издательский дом «Сциентиа», 2024. — С. 333–336.</mixed-citation>
			</ref>
			<ref id="B8">
				<label>8</label>
				<mixed-citation publication-type="confproc">Wang Z. Ocular Feature Extraction for Eye Movement Analysis and Neurological Dysfunction Diagnosis / Z. Wang [et al.] // 2025 IEEE International Conference on Systems, Man, and Cybernetics (SMC). — Vienna, Austria, 2025. — P. 7626–7631. — DOI: 10.1109/SMC58881.2025.11342937.</mixed-citation>
			</ref>
			<ref id="B9">
				<label>9</label>
				<mixed-citation publication-type="confproc">Слядников Е.Е. Модель, алгоритм и программная реализация обработки данных для видеокодека / Е.Е. Слядников // Доклады Томского государственного университета систем управления и радиоэлектроники. — 2012. — № 1-1(25). — С. 65–70.</mixed-citation>
			</ref>
			<ref id="B10">
				<label>10</label>
				<mixed-citation publication-type="confproc">Желтоухов М.О. Система автоматической подготовки датасетов с последующим обучением нейросети для задач компьютерного зрения / М.О. Желтоухов, В.С. Тарасов // Сборник студенческих научных работ факультета компьютерных наук ВГУ : сб. ст. : в 2 ч. / под ред. Д.Н. Борисова. — Воронеж : Воронежский государственный университет, 2019. — № 13, ч. 2. — С. 95–100.</mixed-citation>
			</ref>
			<ref id="B11">
				<label>11</label>
				<mixed-citation publication-type="confproc">B G. Social Media Content Generation: An AI-Based System for Automated Viral Short-Form Video Creation / G. B, K. Somasundaram // 2025 IEEE 2nd International Conference on Information Technology, Electronics and Intelligent Communication Systems (ICITEICS). — Bangalore, India, 2025. — P. 1–9. — DOI: 10.1109/ICITEICS64870.2025.11341675.</mixed-citation>
			</ref>
			<ref id="B12">
				<label>12</label>
				<mixed-citation publication-type="confproc">Антипова С.А. Разработка системы контроля доступа на основе распознавания лиц / С.А. Антипова // Программные продукты и системы. — 2021. — № 2. — С. 245–256. — DOI: 10.15827/0236-235X.134.245-256.</mixed-citation>
			</ref>
			<ref id="B13">
				<label>13</label>
				<mixed-citation publication-type="confproc">Ari N. Matplotlib in python / N. Ari, M. Ustazhanov // 2014 11th International Conference on Electronics, Computer and Computation (ICECCO). — Abuja, Nigeria, 2014. — P. 1–6. — DOI: 10.1109/ICECCO.2014.6997585.</mixed-citation>
			</ref>
		</ref-list>
	</back>
	<fundings/>
</article>