Достижение 100/100 по WCAG 2.1 AA для доступности видео с помощью Cloudinary AI в Next.js

Фото: pen_ash (Pixabay) — https://pixabay.com/photos/motorbike-honda-crf100f-3286222/

Источник: Cloudinary Blog•

Достижение 100/100 по WCAG 2.1 AA для доступности видео с помощью Cloudinary AI в Next.js

Часто задаваемые вопросы. Почему доступность видео часто упускается из виду и каковы юридические стандарты, на которые должны ориентироваться команды? Доступность видео сложна, поскольку требует координации нескольких синхронизированных потоков контента — субтитров, аудиоописаний, карт фокуса…

Доступность видео — одна из наиболее стабильно упускаемых из виду областей веб-соответствия. Большинство разработчиков знают, как добавлять альтернативный текст для изображений, но видео, субтитры, расшифровки, аудиоописания и требования к контрастности сложнее, а инструменты для них беднее.

В этом руководстве описывается, как создать приложение на Next.js 15, которое набирает 100 баллов из 100 по всем семи критериям доступности видео WCAG 2.1 A/AA, причем самые сложные требования обрабатываются с помощью конвейера искусственного интеллекта Cloudinary. Каждый шаг напрямую соотносится с реальным критерием и кодом движка, который его удовлетворяет.

Живая демонстрация:

Закон об американцах с инвалидностью (ADA) применяется к веб-сайтам и размещенному в Интернете видео со времен знакового судебного урегулирования дела Netflix против NAD в 2012 году. С тех пор количество судебных исков, связанных с доступностью в США, растет год от года, причем субтитры к видео входят в число наиболее часто упоминаемых нарушений.

Помимо соблюдения требований, группа людей, которым выгодно доступное видео, больше, чем предполагает большинство команд:

  • 1.5 миллиарда людей по всему миру имеют ту или иную степень потери слуха.
  • 2.2 миллиарда людей имеют нарушение зрения вблизи или вдалеке.
  • Субтитры регулярно используются людьми, смотрящими видео в шумной обстановке, не являющимися носителями языка и всеми, кто лучше воспринимает информацию при одновременном чтении и прослушивании.

WCAG 2.1, опубликованный W3C, является международно признанным техническим стандартом. Уровень A — это минимум; Уровень AA является юридической целью в большинстве юрисдикций (Директива ЕС о доступности веб-сайтов, ADA, Раздел 508).

Этот проект ориентирован на каждый специфичный для видео критерий на Уровнях A и AA. Вот полный набор, требования каждого из них и функции Cloudinary, которые их удовлетворяют:

Архитектура следует трехэтапному потоку:

  • Видео загружается в Cloudinary (прямая загрузка из браузера через неаутентифицированный пресет).
  • Серверный экшен Next.js вызывает Admin API с параметрами auto_transcription: true и auto_chaptering: true.
  • Клиент опрашивает Admin API каждые 4 секунды до появления файла-компаньона .transcript.
  • Плеер перезагружается с включенным обнаружением встроенных субтитров; расшифровка и главы подаются напрямую из CDN Cloudinary.

В этом потоке нигде нет шага ручного создания WebVTT.

Что требует критерий:

Каждое предварительно записанное видео с аудиодорожкой должно иметь синхронизированную дорожку субтитров — текст, отображаемый в синхронизации с произносимым аудио.

Как Cloudinary справляется с этим:

Аддон Cloudinary Video Transcription принимает один вызов API и возвращает два файла-компаньона:

  • {publicId}.transcript: JSON-файл с таймингом слов, содержащий метки времени начала и окончания для каждого слова.
  • {publicId}.vtt: стандартный файл WebVTT.

Оба файла находятся рядом с видео в вашей учетной записи Cloudinary под тем же пространством имен public_id. Плеер Cloudinary Video Player может обнаруживать их автоматически, без необходимости указывать явный URL-адрес.

Одним вызовом Cloudinary ставит задачу ИИ в очередь асинхронно и записывает файлы-компаньоны по завершении.

Прочитайте документацию здесь: uploader.explicit() reference · Video transcription overview

Прочитайте документацию здесь: uploader.explicit() reference · Video transcription overview

Посмотреть app/actions.ts на GitHub: https://github.com/musebe/video-accessibility/blob/main/app/actions.ts

Посмотреть app/actions.ts на GitHub:

Большинство интеграций субтитров требуют создания URL-адреса CDN для файла VTT и передачи его в качестве <track src="...">. С Cloudinary плеер знает имя облака учетной записи и public_id видео, поэтому может автоматически найти .transcript JSON.

Установка maxWords: 5 переключает плеер в режим пошаговых субтитров. Вместо отображения полного блока субтитров он показывает по пять слов за раз, выделяя каждое слово по мере его произнесения (в стиле караоке). Это значительно повышает читаемость для пользователей с когнитивными нарушениями или трудностями чтения.

Когда пользователь исправил расшифровку и загрузил отредактированный VTT, плеер переключается на этот явный URL-адрес:

Прочитайте документацию здесь: Cloudinary Video Player — Text Tracks

Прочитайте документацию здесь: Cloudinary Video Player — Text Tracks

Посмотреть components/VideoPlayer.tsx на GitHub: https://github.com/musebe/video-accessibility/blob/main/components/VideoPlayer.tsx

Посмотреть components/VideoPlayer.tsx на GitHub:

Что требует критерий:

Для предварительно записанного видео со звуком необходимо предоставить либо дорожку аудиоописания, либо полную текстовую альтернативу (расшифровку), описывающую как звуковое, так и визуальное содержание.

Файл расшифровки, лежащий в хранилище, не удовлетворяет этому требованию. Он должен быть представлен пользователю понятным, доступным способом.

Как Cloudinary справляется с этим:

Тот же самый .transcript JSON, который управляет субтитрами, становится источником данных для панели прокручиваемой расшифровки, отображаемой рядом с плеером. Панель остается синхронизированной с воспроизведением путем чтения меток времени на уровне слов из расшифровки.

Как работает опрос Admin API:

Поскольку Cloudinary обрабатывает транскрипцию асинхронно, приложение опрашивает файл каждые четыре секунды с помощью Admin API, который возвращает версионированный secure_url для исходных файлов-компаньонов:

Номер версии в URL обязателен; URL-адреса CDN для исходных файлов этого типа учетной записи без него не разрешаются.

Прочитайте документацию здесь: Admin API — Get resource

Прочитайте документацию здесь: Admin API — Get resource

Панель расшифровки проходит массив строк в обратном порядке при каждом обновлении времени, чтобы найти последнюю произнесенную строку:

Активная строка автоматически прокручивается в область видимости. Прошлые строки затухают до 38% непрозрачности. Нажатие на любую строку перематывает плеер к этой метке времени, превращая расшифровку в полностью интерактивный инструмент навигации, а не в простой сброс текста.

Посмотреть components/TranscriptPanel.tsx на GitHub: https://github.com/musebe/video-accessibility/blob/main/components/TranscriptPanel.tsx

Посмотреть components/TranscriptPanel.tsx на GitHub:

Что требует критерий:

Уровень AA требует наличия дорожки аудиоописания: отдельной дорожки повествования, описывающей визуальный контент, который не передается основным звуком. Для многих видео это означает создание и микширование дополнительной аудиодорожки, что является дорогостоящим и трудоемким.

WCAG 1.2.5 включает признанное исключение. Когда весь визуальный контент уже описан существующей аудиодорожкой, отдельное аудиоописание не требуется. Учебное пособие «говорящая голова», пошаговое руководство с демонстрацией экрана или презентация продукта, где спикер комментирует то, что происходит на экране, подходят под это определение.

Как Cloudinary подтверждает это:

ИИ-транскрипция Cloudinary подтверждает, что аудиодорожка является содержательной. Она создает расшифровку с контентом на уровне слов только в том случае, если аудио содержит речь. Если бы видео было беззвучным или содержало только фоновую музыку, расшифровка была бы пустой или отсутствовала бы.

Приложение использует завершение транскрипции в качестве сигнала подтверждения:

В деталях аудита написано: «Комментарий спикера описывает содержимое на экране — аудиоописание удовлетворено устным комментарием».

Посмотреть components/VideoAccessibilityClient.tsx на GitHub: https://github.com/musebe/video-accessibility/blob/main/components/VideoAccessibilityClient.tsx

Посмотреть components/VideoAccessibilityClient.tsx на GitHub:

Главы сами по себе не являются жестким требованием WCAG, но они улучшают навигацию для пользователей клавиатуры и скринридеров, особенно для длинных видео. Они являются лучшей практикой WCAG в рамках Рекомендации 2.4 (Навигация).

Как Cloudinary генерирует главы:

Тот же вызов uploader.explicit(), который запускает транскрипцию, также активирует создание глав с помощью ИИ, если установлен параметр auto_chaptering: true. Модель Cloudinary сегментирует видео по темам и записывает маркеры глав как часть внутренней дорожки глав плеера.

Как плеер обнаруживает главы:

Главы не возвращаются в виде файла CDN; они существуют как внутренняя текстовая дорожка внутри плеера. Приложение опрашивает p.textTracks() каждые три секунды после инициализации плеера:

Как только главы найдены, они передаются родителю через onChaptersDiscovered и отображаются во встроенной кнопке меню глав плеера (chaptersButton: true).

Ознакомьтесь с документацией здесь: Cloudinary Video Player — Chapters

Ознакомьтесь с документацией здесь: Cloudinary Video Player — Chapters

Посмотреть components/VideoPlayer.tsx на GitHub:

Посмотреть components/VideoPlayer.tsx на GitHub:

Что требует критерий:

Каждый элемент управления плеером (воспроизведение, пауза, перемотка, громкость, полноэкранный режим, переключение субтитров, меню глав) должен быть доступен и управляем только с помощью клавиатуры. Это исключает кастомные плееры, созданные из несемантического HTML без явной обработки клавиатуры.

Как с этим справляется Cloudinary:

Cloudinary Video Player создан на базе Video.js, которая из коробки поддерживает полную модель взаимодействия с клавиатурой. Никакого дополнительного кода не требуется.

Кнопка глав, меню стилей субтитров и все элементы управления плеером полностью доступны при навигации с помощью клавиши Tab. Все, что нужно сделать, — это установить controls: true в конфигурации плеера.

Ознакомьтесь с документацией здесь: Cloudinary Video Player configuration

Ознакомьтесь с документацией здесь: Cloudinary Video Player configuration

Посмотреть components/VideoPlayer.tsx на GitHub:

Посмотреть components/VideoPlayer.tsx на GitHub:

Что требует критерий:

Если контент перемещается, мигает или прокручивается автоматически более 5 секунд, должен быть предусмотрен механизм его паузы или остановки. Автовоспроизведение видео — одно из самых частых нарушений и один из самых негативных факторов для пользователей с расстройствами внимания, вестибулярными нарушениями или использующих программы чтения с экрана.

Как с этим справляется Cloudinary:

Cloudinary Video Player не запускает автовоспроизведение по умолчанию. Свойство autoplay должно быть явно задано для его включения. Если его опустить, плеер запускается в состоянии паузы с постоянно видимой и доступной для фокусировки нативной кнопкой воспроизведения.

Это единственное упущение в конфигурации удовлетворяет критерию для всех видео в приложении.

Что требует критерий:

Текст нормального размера должен иметь коэффициент контрастности не менее 4,5:1 по отношению к своему фону. Это относится к меткам пользовательского интерфейса плеера, тексту субтитров и любой наложенной информации.

Две вещи, работающие вместе:

1. Цветовая тема плеера

Cloudinary Video Player принимает объект colors, который управляет панелью управления:

2. Тень текста субтитров для наложения на видео

Текст субтитров появляется поверх непредсказуемого видеоконтента. Вместо требования черного фонового блока, тень текста CSS обеспечивает читаемость на любом кадре:

Этот подход поддерживает визуальную чистоту субтитров, сохраняя при этом требуемый WCAG контраст во всех условиях.

Посмотреть app/globals.css на GitHub: https://github.com/musebe/video-accessibility/blob/main/app/globals.css

Посмотреть app/globals.css на GitHub:

Что требует критерий:

Каждый компонент пользовательского интерфейса должен иметь программно определяемое имя, которое вспомогательные технологии могут читать вслух. Элемент <video> без метки озвучивается программами чтения с экрана просто как «видео», что является неоднозначным и бесполезным, особенно когда на странице появляется несколько видео.

Один атрибут для нативного элемента видео:

Поскольку Cloudinary Video Player монтируется поверх стандартного элемента <video>, которым мы управляем, aria-label распространяется по доступному дереву DOM плеера. В продакшн-приложении эта метка должна описывать реальное содержание видео (например, «Введение в трансформации Cloudinary»).

Посмотреть components/VideoPlayer.tsx на GitHub:

Посмотреть components/VideoPlayer.tsx на GitHub:

Хотя это и не жесткое требование WCAG, предоставление возможности настройки стиля субтитров значительно улучшает взаимодействие для пользователей с ослабленным зрением, светочувствительностью или дислексией. Приложение поставляется с шестью пресетами, каждый из которых внедряется динамически через блок <style> без необходимости повторной загрузки плеера.

Посмотреть components/CaptionStylePicker.tsx на GitHub: https://github.com/musebe/video-accessibility/blob/main/components/CaptionStylePicker.tsx

Посмотреть components/CaptionStylePicker.tsx на GitHub:

Приложение включает функцию runWcagAudit(), которая оценивает состояние плеера во время выполнения и возвращает результат прохождения/непрохождения для каждого критерия с подробным текстом. Именно это управляет панелью соответствия требованиям в реальном времени, видимой в приложении.

Итак, почему аудит во время выполнения, а не статический линт?

Некоторые критерии нельзя оценить статически. Существуют ли субтитры, зависит от того, завершила ли Cloudinary транскрипцию. Отключено ли автовоспроизведение, зависит от конфигурации плеера во время выполнения. Аудит запускается при каждом рендере и обновляется в реальном времени: оценка меняется с ~57 до 100 в момент завершения опроса стенограммы.

Оценка представляет собой процент: пройдено / всего × 100. Когда все семь критериев пройдены, оценка равна 100.

Посмотреть lib/wcagAudit.ts на GitHub: https://github.com/musebe/video-accessibility/blob/main/lib/wcagAudit.ts

Посмотреть lib/wcagAudit.ts на GitHub:

Как только загружается видео с голосовым сопровождением и завершается конвейер транскрипции Cloudinary, все семь критериев проходят одновременно:

Оценка: 100 / 100

Оценка не статична. Она начинается ниже при первой загрузке видео, до завершения транскрипции, и поднимается до 100 по мере завершения работы конвейера ИИ. Это отражает фактическое состояние соответствия плеера в любой заданный момент времени.

Ресурсы:

  • Живая демонстрация:

Живая демонстрация:

Репозиторий GitHub:

  • Транскрипция и создание резюме видео

Транскрипция и создание резюме видео

  • Upload API — метод explicit()

Upload API — метод explicit()

  • Admin API — Получить ресурс

Admin API — Получить ресурс

  • Cloudinary Video Player

Cloudinary Video Player

  • Текстовые дорожки (субтитры, главы)

Текстовые дорожки (субтитры, главы)

WebAIM — Субтитры, стенограммы и аудиоописания

MDN — Формат WebVTT

О чём эта статья

Ещё в разделе «Медиа, контент и развлечения»

Все →

Ещё от Cloudinary