Анализ технической схемы и реализация записи веб-экрана

внешний интерфейс JavaScript WebRTC
Анализ технической схемы и реализация записи веб-экрана

阿余.png

Это 121-я оригинальная статья без воды.Если вы хотите получить больше оригинальных статей, выполните поиск в общедоступном аккаунте и подпишитесь на нас~ Эта статья была впервые опубликована в блоге Zhengcaiyun:Анализ технической схемы и реализация записи веб-экрана

предисловие

С быстрым развитием Интернет-технологий технология записи веб-экрана стала зрелой. Например, технология записи экрана может применяться к онлайн-экзаменам для осуществления удаленного наблюдения, совместного использования экрана и записи экрана. ясно Это указывает на неправильный путь воспроизведения, и технология записи экрана может помочь нам найти и воспроизвести проблему. Затем в этой статье мы поделимся с читателями технологией записи экрана с двух аспектов: запись экрана с обнаружением и запись экрана без распознавания, в надежде помочь вам получить предварительное представление о записи экрана веб-страницы.

Что такое запись чувствительного экрана?

Запись чувствительного экрана обычно относится к получению авторизации пользователя или уведомлению пользователя о том, что следующая операция будет записана как видео, и во время процесса записи пользователь имеет право закрыть и прервать запись экрана. То есть, до или во время записи экрана пользователь всегда может решить, может ли быть выполнена запись экрана.

Чувствительная запись экрана на основе WebRTC

Решения для записи экрана, основанные на здравом смысле, в основномWebRTCзаписывать.WebRTCЭто набор технических решений для потоковой передачи данных в реальном времени на основе аудио- и видеодорожек. Собственный API, предоставляемый браузеромnavigator.mediaDevices.getDisplayMediaРеализация метода предлагает пользователю выбрать и разрешить захват отображаемого содержимого или окна, а затем получает поток (записанный аудио- и видеопоток экрана). Мы можем преобразовать поток в соответствующие мультимедийные данные и сохранить их данные. Когда содержимое записи необходимо отследить позже, данные мультимедиа извлекаются и воспроизводятся.

Конкретный процесс записи экрана выглядит следующим образом:

Реализуйте начальную запись экрана и хранение данных

использоватьnavigator.mediaDevices.getDisplayMediaИнициализируйте запись экрана и вызовите всплывающее окно для авторизации пользователя.Схема эффекта выглядит следующим образом:

Основной код для реализации записи экрана инициализации WebRTC выглядит следующим образом:

const tracks = []; // 媒体数据
const options = {
  mimeType : "video/webm; codecs = vp8", // 媒体格式
};
let mediaRecorder;
// 初始化请求用户授权监控
navigator.mediaDevices.getDisplayMedia(constraints).then((stream) => {
  // 对音视流进行操作
  startFunc(stream);
});
// 开始录制方法
function start(stream) {
  // 创建 MediaRecorder 的实例对象,对指定的媒体流进行录制
  mediaRecorder = new MediaRecorder(stream, options);
  // 当生成媒体流数据时触发该事件,回调传参 event 指本次生成处理的媒体数据
  mediaRecorder.ondataavailable = event => {
     if(event?.data?.size > 0){
      tracks.push(event.data); // 存储媒体数据
    }
  };
  mediaRecorder.start();
  console.log("************开始录制************")
};
// 结束录制方法
function stop() {
  mediaRecorder.stop();
  console.log("************录制结束************")
}
// 定义constraints数据类型
interface constraints {
  audio: boolean | MediaTrackConstraints, // 指定是否请求音轨或者约束轨道属性值的对象
  video: boolean | MediaTrackConstraints, // 指定是否请求视频轨道或者约束轨道属性值的对象
}

Реализуйте запись экрана и откат

Чтобы получить медиаданные этой записи экрана, вы можете преобразовать ее в объект большого двоичного объекта, сгенерировать строку URL-адреса объекта большого двоичного объекта и назначить ее в video.src для воспроизведения результата записи. Эффект ретроспективного видео выглядит следующим образом:

Основной код метода трассировки записи экрана выглядит следующим образом:

// 回放录制内容
function replay() {
  const video = document.getElementById("video");
  const blob = new Blob(tracks, {type : "video/webm"});
  video.src = window.URL.createObjectURL(blob);
  video.srcObject = null;
  video.controls = true;
  video.play();
}

Функция прямой трансляции в реальном времени

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

Основной код для реализации прямой трансляции в реальном времени выглядит следующим образом:

// 直播
function live() {
  const video = document.getElementById("video");
  video.srcObject = window.stream;
  video.controls = true;
  video.play();
}

Совместимость с браузером

Что такое бессмысленная запись экрана?

Запись экрана без распознавания означает запись действий пользователя на странице без восприятия пользователем. Разница между реализацией и сенсорной записью заключается в том, что безсенсорная запись обычно записывается с использованием DOM страницы записи. Общие решения включают в себя создание скриншотов на холсте, видео и запись rrweb.

Видео рисования скриншотов на холсте

Когда пользователи просматривают страницу, они могут рисовать несколько снимков экрана DOM через холст, а затем объединять несколько снимков экрана в видеозапись экрана. Однако, учитывая, что количество видеокадров составляет 30 кадров, количество кадров представляет собой количество снимков экрана, необходимых в секунду.Для плавности и четкости видео каждый снимок экрана составляет 400 КБ, тогда, когда длина видео составляет 1 минуту, для загрузки требуется 703,125 МБ. Такая большая трата полосы пропускания, несомненно, приведет к снижению производительности и даже повлияет на работу пользователей.Не рекомендуется использовать его, и реализация этого решения не будет здесь подробно описываться.

запись rrweb

rrweb(запись и воспроизведение в Интернете) — очень хорошая поддержка записи DOM.Он использует мощный API, предоставляемый современными браузерами, для записи и воспроизведения пользовательских операций в любом веб-интерфейсе и может эффективно преобразовывать структуру DOM страницы с помощью соответствующих алгоритмов. Библиотека данных JSON с открытым исходным кодом. По сравнению с использованием холста для рисования и записи экрана, rrweb делает передачу данных по сети быстрее и легче благодаря тому, что запись не пропускает кадры, что значительно оптимизирует производительность сети.

rrwebБиблиотеки с открытым исходным кодом в основном состоят изrrweb-snapshot, **rrweb** иrrweb-playОн состоит из трех частей и предоставляет такие функции, как фильтрация действий, шифрование данных, сжатие данных, нарезка данных и маскирование элементов.

rrweb-snapshot

rrweb-snapshotпоставкаsnapshotа такжеrebuildДва API-интерфейса, которые соответственно реализуют две функции создания структуры данных сериализуемого виртуального моментального снимка DOM и реконструкции его структуры данных в соответствующие узлы DOM.

snapshotПреобразуйте DOM и его состояние в сериализуемую структуру данных и добавьте уникальный идентификатор id, чтобы идентификатор отображал соответствующий узел DOM, что удобно для последующих инкрементных операций.

Во-первых, необходимо создать начальный снимок DOM путем глубокого копирования документа.

// 深拷贝 document 节点
const docEl = document.documentElement.cloneNode(true);
// 回放时再将深拷贝的节点挂在回去即可
document.replaceChild(docEl, document.documentElement);

Поскольку полученный DOM-объект не сериализуем, его все равно необходимо преобразовать в определенный текстовый формат (например, JSON) для передачи, иначе удаленная запись невозможна. В процессе реализации сериализации снимков DOM также требуется специальная обработка данных:

  1. Измените относительный путь на абсолютный;
  2. Измените стиль ссылки на страницу на встроенный стиль;
  3. Скрипты не могут запускаться, любой JavaScript на записанной странице не должен выполняться. Пучок<script>Превратиться в<noscrpit>;
  4. Благодаря некоторым формам (например,<input type="text" />) не будет отображать значение в html, поэтому вам нужно прочитать значение формы.

Хотя полное количество объектов DOM можно получить, невозможно связать взаимодействующие узлы DOM в инкрементальном снимке с существующими узлами DOM, поэтому необходимо добавить отношение отображения (id => Node) в DOM. узлов DOM записываются через этот идентификатор и соответствуют полным узлам DOM.

Ниже приведен узел DOM, полученный изначально:

<html>
  <body>
    <header>
    </header>
  </body>
</html>

При обходе всего дерева DOM с узлами Node в качестве единицы к каждому пройденному узлу добавляется уникальный идентификатор id для создания полностью сериализованного моментального снимка объекта DOM. Ниже приведено схематическое представление сериализованной структуры данных:

{
  "type": "Document",
  "childNodes": [
    {
      "type": "Element",
      "tagName": "html",
      "attributes": {},
      "childNodes": [
        {
          "type": "Element",
          "tagName": "head",
          "attributes": {},
          "childNodes": [],
          "id": 3
        },
        {
          "type": "Element",
          "tagName": "body",
          "attributes": {},
          "childNodes": [
            {
              "type": "Text",
              "textContent": "\n    ",
              "id": 5
            },
            {
              "type": "Element",
              "tagName": "header",
              "attributes": {},
              "childNodes": [
                {
                  "type": "Text",
                  "textContent": "\n    ",
                  "id": 7
                }
              ],
              "id": 6
            }
          ],
          "id": 4
        }
      ],
      "id": 2
    }
  ],
  "id": 1
}
  • rebuild

БудуsnapshotЗапишите структуру данных исходного снимка, а затем перестройте DOM, рекурсивно добавив атрибуты к каждому узлу, в результате чего получится сериализуемый снимок узла DOM.

rrweb

rrwebпоставкаrecordа такжеreplayДва API соответственно реализуют две функции записи всех добавочных данных и воспроизведения записанных данных в соответствии с меткой времени.

  • record

Перехватывайте данные добавочных изменений и сохраняйте их в объектах JSON, инициируя изменения представления и изменения структуры DOM (такие как удаление узла DOM и изменения значений атрибутов). Каждое добавочное данные соответствует отметке времени, и эти данные называются Oplog (журнал операций).

Изменения представления могут собирать дополнительные данные с помощью методов глобального мониторинга событий и прокси-серверов событий. Большинство этих событий связаны с рабочим поведением пользователя и действиями, которые могут инициировать такие события, такие как изменение узла DOM или содержимого, движение или взаимодействие мыши, страница или прокрутка элементов, взаимодействие с клавиатурой и изменение размера окна.

Изменения в структуре DOM могут быть предоставлены браузеромMutationObserverИнтерфейс может отслеживать, инициировать обратные вызовы параметров, получать информацию об узле этого изменения DOM, а затем фильтровать и реорганизовывать данные. Структура данных параметров обратного вызова выглядит следующим образом:

let MutationRecord1: MutationRecordObject[];
interface MutationRecordObject {
  /**
   * 如果是属性变化,则返回 "attributes";
   * 如果是 characterData 节点变化,则返回 "characterData";
   * 如果是子节点树 childList 变化,则返回 "childList"。
  */
  type: String,
  // 返回被添加的节点。如果没有节点被添加,则该属性将是一个空的 NodeList。
  addedNodes: NodeList,
  // 返回被移除的节点。如果没有节点被移除,则该属性将是一个空的 NodeList。
  removedNodes: NodeList,
  // 返回被修改的属性的属性名,或者 null。
  attributeName: String | null,
  // 返回被修改属性的命名空间,或者 null。
  attributeNamespace: String | null,
  // 返回被添加或移除的节点之前的兄弟节点,或者 null。
  previousSibling: Node | null,
  // 返回被添加或移除的节点之后的兄弟节点,或者 null。
  nextSibling: Node | null,
  /** 返回值取决于 MutationRecord.type。
   * 对于属性 attributes 变化,返回变化之前的属性值。
   * 对于 characterData 变化,返回变化之前的数据。
   * 对于子节点树 childList 变化,返回 null。
  */
  oldValue: String | null,
}

Структура данных Oplog, собранная по записи, показана на следующем рисунке:

let Oplog: OplogObject[];
interface OplogObject {
  /** 返回值取决于收集的事件类型
   * DomContentLoaded: 0, Load: 1,
   * FullSnapshot: 2, IncrementalSnapshot: 3,
   * Meta: 4, Custom: 5, Plugin: 6
  */
  type: Number,
  data: {
    // 返回添加的节点数据
    adds: [],
    // 返回修改的节点属性数据
    attributes: [],
    // 返回移除的节点属性数据
    removes: [],
    /** 返回值取决于增量数据的增量类型
     * Mutation: 0, MouseMove: 1,
     * MouseInteraction: 2, Scroll: 3,
     * ViewportResize: 4, Input: 5,
     * TouchMove: 6, MediaInteraction: 7,
     * StyleSheetRule: 8, CanvasMutation: 9,
     * Font: 10, Log: 11,
     * Drag: 12, StyleDeclaration: 13
    **/
    source: Number,
    // 返回当前修改的值,无则不返回
    text: String | undefined,
  },
  // 当前时间戳
  timestamp: Number,
}
  • replay

На основе данных инициализированного моментального снимка и добавочных данных они воспроизводятся один за другим в соответствии с соответствующей меткой времени. Поскольку выполнение скрипта отключается при создании моментального снимка, полный моментальный снимок DOM может быть реконструирован с использованием iframe в качестве контейнера, а такие операции, как выполнение скрипта, всплывающие окна и отправка форм, отключаются с помощью атрибута sanbox. Поместите Oplog в очередь операций, отсортируйте их по каждой метке времени, а затем используйте таймер requestAnimationFrame для воспроизведения снимков Oplog.

rrweb-player

Предоставьте набор элементов управления пользовательского интерфейса для rrweb, предоставляя функции на основе графического интерфейса, такие как пауза, быстрая перемотка вперед, перетаскивание для воспроизведения в любой момент времени.

Суммировать

В этой статье анализируется реализация решения для записи экрана с точки зрения чувств и переживаний. Сценарии применения записи экрана страницы относительно богаты.Запись по ощущениям обычно используется в интерактивных сценариях в реальном времени, таких как онлайн-экзамены веб-страницы, прямые трансляции, голосовые и видеозвонки, в то время как запись без распознавания больше используется в важных операционных записях. , сценарии воспроизведения ошибок и продукты.Оперативный анализ привычек пользователей и другие сценарии, каждый из которых имеет свои достоинства. Основываясь на безопасности и конфиденциальности пользовательских данных, Zhengcaiyun в настоящее время предпочитает использовать сенсорную запись для пилотных испытаний, чтобы избежать споров о безопасности. Хотя технологическое решение для записи экрана постоянно совершенствуется и совершенствуется, мы также должны уважать безопасность и конфиденциальность данных пользователя и выбирать решение, которое больше подходит для наших собственных сценариев.

Ссылаться на

rrweb

Как использовать JS для записи и воспроизведения страницы

Рекомендуемое чтение

Минимальные запасы для электронной коммерции — артикул и реализация алгоритма

Что нужно знать об управлении проектами

Перекомпоновка и перерисовка рендеринга браузера

Сценарии и приложения для предотвращения дрожания

работы с открытым исходным кодом

  • Zhengcaiyun интерфейсный таблоид

адрес с открытым исходным кодомwww.zoo.team/openweekly/(На главной странице официального сайта таблоида есть группа обмена WeChat)

  • skuDemo

адрес с открытым исходным кодомGitHub.com/Chinese Patent Medicine-Inc/Reservoir…

Карьера

ZooTeam, молодая, увлеченная и творческая команда, связанная с отделом исследований и разработок продукции Zhengcaiyun, базируется в живописном Ханчжоу. В настоящее время в команде более 50 фронтенд-партнеров, средний возраст которых составляет 27 лет, и почти 30% из них — инженеры с полным стеком, настоящая молодежная штурмовая группа. В состав членов входят «ветераны» солдат из Ali и NetEase, а также первокурсники из Чжэцзянского университета, Университета науки и технологий Китая, Университета Хандянь и других школ. В дополнение к ежедневным деловым связям, команда также проводит технические исследования и фактические боевые действия в области системы материалов, инженерной платформы, строительной платформы, производительности, облачных приложений, анализа и визуализации данных, а также продвигает и внедряет ряд внутренних технологий. Откройте для себя новые горизонты передовых технологических систем.

Если вы хотите измениться, вас забрасывают вещами, и вы надеетесь начать их бросать; если вы хотите измениться, вам сказали, что вам нужно больше идей, но вы не можете сломать игру; если вы хотите изменить , у вас есть возможность добиться этого результата, но вы не нужны; если вы хотите изменить то, чего хотите достичь, вам нужна команда для поддержки, но вам некуда вести людей; если вы хотите изменить установившийся ритм, это будет "5 лет рабочего времени и 3 года стажа работы"; если вы хотите изменить исходный Понимание хорошее, но всегда есть размытие того слоя оконной бумаги.. , Если вы верите в силу веры, верьте, что обычные люди могут достичь необыкновенных вещей, и верьте, что они могут встретить лучшего себя. Если вы хотите участвовать в процессе становления бизнеса и лично способствовать росту фронтенд-команды с глубоким пониманием бизнеса, надежной технической системой, технологиями, создающими ценность, и побочным влиянием, я думаю, что мы должны говорить. В любое время, ожидая, пока вы что-нибудь напишете, отправьте это наZooTeam@cai-inc.com