MediaPipe Gesture Recognizer можно освоить на одном небольшом проекте, если сразу видеть вход, действие и результат. MediaPipe Tasks Vision запускает модель распознавания жестов в браузере и возвращает категорию, уверенность и координаты руки для каждого кадра. Ниже вы соберёте работающий пример и проверите обычный и граничный сценарии.
Если привязать действие к каждому video frame, один жест переключит слайд десятки раз и интерфейс станет непредсказуемым. Поэтому отделим настройку, входные данные, основное действие и проверку. В этой статье вы соберёте демо с веб-камерой, где Thumb Up переходит к следующей карточке, Open Palm возвращает предыдущую, а cooldown защищает от повторов. Проверка: после разрешения камеры видео появляется, уверенный жест меняет карточку один раз, а отсутствие руки не вызывает действий.
запросить video без audio после клика. Не расширяйте проект до первого успешного запуска.
runningMode VIDEO готов к кадрам. Проверяйте значение, а не отсутствие ошибки.
После успеха добавьте нейтральный жест подтверждения и отдельную кнопку остановки камеры. Так копирование станет практикой.
Как устроен учебный проект MediaPipe Gesture Recognizer
getUserMedia создаёт видеопоток, requestAnimationFrame передаёт новые кадры распознавателю, а отдельная функция превращает устойчивый жест в действие интерфейса. Держите ввод, логику и отображение раздельно: тогда каждый этап можно проверить отдельно.
| Этап | Действие | Проверяемый результат |
|---|---|---|
| Камера | запросить video без audio после клика | элемент video показывает локальный поток |
| Модель | загрузить FilesetResolver и GestureRecognizer | runningMode VIDEO готов к кадрам |
| Цикл | анализировать только новый video.currentTime | результат содержит категорию и score |
| Действие | применить порог и cooldown | один жест меняет слайд ровно один раз |
Контрольные точки: камера, модель, цикл и действие. Следующий шаг начинается после совпадения с ожидаемым результатом.

От входных данных до видимого результата. Сначала проверяется вход, затем действие и только потом интерфейс.
Собираем рабочий пример шаг за шагом
Пример сверялся с актуальной документацией официальной документации MediaPipe Gesture Recognizer for Web на 19 октября 2026 года. Создайте Vite-проект, установите @mediapipe/tasks-vision и запускайте через localhost или HTTPS, иначе камера может быть недоступна. Проверьте текущую папку через pwd или Get-Location. Вставьте пример целиком, выполните один раз, затем разбирайте по частям.
import { FilesetResolver, GestureRecognizer } from '@mediapipe/tasks-vision'
const video = document.querySelector('video')
const label = document.querySelector('#gesture')
let recognizer
let lastVideoTime = -1
let lastActionAt = 0
async function start() {
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false })
video.srcObject = stream
await video.play()
const vision = await FilesetResolver.forVisionTasks('/wasm')
recognizer = await GestureRecognizer.createFromOptions(vision, {
baseOptions: { modelAssetPath: '/gesture_recognizer.task' },
runningMode: 'VIDEO',
numHands: 1,
})
requestAnimationFrame(loop)
}
function loop() {
if (video.currentTime !== lastVideoTime) {
const result = recognizer.recognizeForVideo(video, performance.now())
const best = result.gestures[0]?.[0]
label.textContent = best ? best.categoryName + ' ' + best.score.toFixed(2) : 'Нет руки'
if (best && best.score > 0.7 && performance.now() - lastActionAt > 900) {
if (best.categoryName === 'Thumb_Up') nextSlide()
if (best.categoryName === 'Open_Palm') previousSlide()
lastActionAt = performance.now()
}
lastVideoTime = video.currentTime
}
requestAnimationFrame(loop)
}- После клика браузер запрашивает камеру и показывает локальный видеопоток.
- Распознанный жест и score видны текстом, а действие срабатывает только выше порога 0.7.
- Повторный запуск даёт тот же предсказуемый результат.
- Пустой ввод получает понятное сообщение вместо падения.
Модель отвечает за классификацию кадра, а порог, cooldown и смысл жеста задаёт приложение. Найдите в примере вход, проверку и место формирования результата.

Что отличает устойчивый проект от случайного запуска. Явные границы делают ошибку локальной и понятной.
Что происходит внутри и почему это работает
recognizeForVideo получает кадр и timestamp. Результат может быть пустым, содержать несколько рук и несколько категорий. Optional chaining защищает код от отсутствующих результатов. Логику держите отдельно от вывода: функция получает аргумент и возвращает значение, а интерфейс показывает его. Синхронное распознавание в основном потоке может блокировать интерфейс. Для тяжёлого сценария перенесите вычисления в Web Worker, как рекомендует документация.
| Часть | За что отвечает | Что проверить |
|---|---|---|
| MediaStream | доставляет кадры камеры в video | поток запускается только после разрешения |
| Recognizer | возвращает жесты, score и landmarks | runningMode совпадает с методом VIDEO |
| Контроллер | применяет порог, cooldown и действие | один устойчивый жест не повторяется каждый кадр |
Score не является гарантией правильности. Освещение, фон, положение ладони и модель камеры меняют качество. Пользователь должен видеть распознанную команду и иметь обычные кнопки. Не делайте жест единственным способом выполнить важное действие. Не прячьте поток в одном обработчике: сохраните вход, проверьте его, вызовите операцию и только затем обновите интерфейс.
Проверяем проект и добавляем свою функцию
Добавьте состояние armed: действие разрешается только после жеста Closed_Fist, а затем ждёт Thumb_Up. Это уменьшит случайные команды. До правки запишите ожидаемое поведение одним предложением. После граничного теста повторите обычный сценарий.
- Сохраните ожидаемый результат: после разрешения камеры видео появляется, уверенный жест меняет карточку один раз, а отсутствие руки не вызывает действий.
- Измените правило: добавьте нейтральный жест подтверждения и отдельную кнопку остановки камеры. Сначала предскажите итог.
- Передайте граничное значение и убедитесь, что приложение не падает.
- Верните корректные данные и объясните роли трёх основных частей.
- элемент video показывает локальный поток
- runningMode VIDEO готов к кадрам
- результат содержит категорию и score
- один жест меняет слайд ровно один раз
Надёжность интерфейса определяется не только моделью, но и правилами между последовательными кадрами. Полезная правка проходит от нового ввода до видимого результата.

Четыре проверки перед следующим шагом. Каждый следующий этап начинается после наблюдаемого результата.
Что запомнить и куда двигаться дальше
Останавливайте tracks при уходе со страницы, явно показывайте активную камеру и не отправляйте кадры на сервер без необходимости и согласия. Для закрепления откройте в распознавании текста с фото, в локальном ИИ в браузере и в AI-расширении Chrome.
Как изучить тему в Кодике
Сначала закрепите async/await, mediaDevices и requestAnimationFrame, затем подключайте модель. Сначала восстановите главную функцию и проверьте её на трёх значениях.
| Шаг | Что разобрать | Мини-проверка |
|---|---|---|
| 1. Основа | DOM, async/await, модули и видеопоток | Объясните вход и выход функции. |
| 2. Инструмент | FilesetResolver, runningMode VIDEO и recognizeForVideo | Повторите команду по памяти. |
| 3. Проект | Порог, cooldown и две команды интерфейса | Проверьте два сценария. |
| 4. Рефакторинг | Worker, сглаживание и приватность камеры | Разделите ввод, логику и вывод. |
Протестируйте разные руки, освещение, отсутствие камеры и отказ разрешения до добавления новых жестов. Базовый синтаксис закрепите через курс JavaScript.
Один жест вызывает десятки команд. Добавьте cooldown или конечный автомат.
Когда рука исчезает, обращение к gestures[0][0] падает. Используйте optional chaining.
Метод VIDEO не соответствует конфигурации IMAGE. Создайте recognizer с VIDEO.
Пользователь без камеры или с ограничениями не может управлять. Оставьте доступный fallback.
Что получится в итоге

Так выглядит законченный учебный проект: есть понятный вход, видимый результат, защита от неверных данных и место для следующего улучшения.
Зачем нужен cooldown?
Он не даёт одному жесту запускать действие на каждом видеокадре.
Что возвращает Gesture Recognizer кроме имени?
Уверенность категории, landmarks руки и дополнительные данные результата.
Что проверять первым, если MediaPipe Gesture Recognizer не запускается?
Версию среды, текущую папку, команду запуска и первую строку ошибки.
Как понять, что проект MediaPipe Gesture Recognizer работает?
Проверьте основной сценарий, неверный ввод, повторный запуск и один граничный случай.
Можно ли начать с готового кода?
Да. Добейтесь результата, измените одно правило и восстановите ключевую функцию без копирования.
Выберите одно улучшение и проведите его от ввода до результата.
Если не хватает основы, перейдите курс JavaScript, затем восстановите ключевую функцию без подсказки.