HTML视频带有全屏聊天叠加层
#aws #javascript #amazonivs #chat

我最近一直专注于聊天,因为我觉得这是任何实时流媒体用户生成的内容(UGC)平台的重要功能。在过去的6周中,我们学会了如何使用create a chat room and integrate it into a live streaming application,以及如何调整聊天消息(以automatedmanual的方式)。我们甚至研究了如何使用Amazon Interactive Video Service(Amazon IVS)聊天来创建interactive whiteboard。在这篇文章中,我们不会查看Amazon IVS聊天的任何特定内容,而是通过将聊天视图叠加在全屏视频之上来增强用户体验的方法。

本机控制的问题

HTML中的<video>标签的好处是,它允许用户通过单击本机浏览器控件中的按钮或双击视频本身来全屏。这是Chrome中的本机控制按钮:

Native HTML video tag in Chrome

大兔子使用的静止图

这允许正在播放的视频填充我们的整个显示。

Fullscreen video

但是,在此观点中,所有附近的内容或其他元素 - 甚至是绝对定位的视频上覆盖的元素 - 甚至是覆盖的元素。如果适合您的要求,那就太好了!但是,有时我们的要求需要更自定义的视图,其中包含全屏视图中的其他元素。

如果您考虑一个典型的直播UGC平台,则很多时候,该视频伴随着附近某个地方的实时聊天流。这样的东西:

Chat next to video

聊天为实时流媒体平台添加了一层交互性。我们的观众可以积极参与对话,而不是被动地消费。那么,为什么在全屏观看时不可见聊天呢?创建像这样的沉浸式全屏体验会更好吗?

Full screen video with chat overlay

解决方案 - 全屏API和CSS

在查看所涉及的代码之前,让我们看一下成品,以便看到我们要实现的效果。为了使事情变得简单并专注于CSS和HTML API,该演示不包含实际的实时流或聊天。相反,聊天消息直接添加到聊天容器中,以模拟真实的聊天体验,以便您可以在全屏中看到什么消息。

注意:代码epens被嵌入到dev.to上的<iframe>中,其中不包括全屏幕的权限。到try out the demo,在新的浏览器选项卡中打开它,然后单击视频播放器右上角的全屏图标。

为了实现这种增强的用户体验,我们将隐藏本机控件,并使用伪级使用HTML Fullscreen API和一些CSS,以在完整屏幕上使用伪级来修改元素的外观和位置。另一种方法是聆听fullscreenchange事件并添加/删除类以每个视图获得不同的样式,但这将涉及很多JavaScript,我个人发现伪级方法的方法清洁器易于使用,并且可以使用。

注意: :fullscreen伪级在现代浏览器中得到很好的支持,但有一些警告。例如,Safari使用非标准:-webkit-full-screen名称。在您的生产应用程序中实施之前,请确保检查support and limitations

全屏API

HTML全屏API使我们可以在全屏视图中提供一个特定的HTML节点。这听起来可能很明显,但是您可能没有意识到它可以在全屏模式下呈现任何 html元素。这意味着我们可以隐藏本机浏览器控件,并将视频播放器和聊天元素组包裹在单个<div>中,并在整个布局中全面进行全屏。我们需要添加自己的全屏按钮以及播放和音量控件,因为视频控件中的内置按钮只能使<video>本身全屏。

让我们看一个典型的视频/聊天视图的简化示例。我将在这里使用Bootstrap,但是您可以使用任何您喜欢的CSS框架。这里对这里的标记进行了大量评论,以帮助您了解发生了什么。专注于重要的位,造型(布局,边界,阴影等)的类已被...替换。

<div class="row" id="video-chat-container">

  <!-- left (video) column -->
  <div class="...">
    <!-- relative position container for video -->
    <div>
      <!-- fix the video container to 16x9-->
      <div class="ratio ratio-16x9">
        <video
          id="video-player"
          class="..."
          src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
          autoplay playsinline muted>
        </video>
      </div>
      <!-- video overlay for status indicator and fullscreen button -->
      <div
        id="top-overlay"
        class="...">
        <!-- status indicator in the top left -->
        <div>
          <span id="online-indicator" class="...">Offline</span>
        </div>
        <!-- manual fullscreen button in the top right -->
        <div>
          <i
            id="fullscreen-toggle-btn"
            role="button"
            class="...">
          </i>
        </div>
      </div>
      <div id="bottom-overlay">
        <!-- bottom div for player controls -->
      </div>
    </div>
  </div>

  <!-- right (chat) container -->
  <div class="...">
    <!-- vertically stack the controls with flex and fill the height of the row-->
    <div
      id="chat-container"
      class="vstack ...">
      <!-- the chat div - fill the height of the container (minus the chat input container height)-->
      <div
        id="chat"
        class="flex-grow-1 ...">
      </div>
      <!-- chat input and submit button -->
      <div
        id="chat-input-container"
        class="flex-grow ...">
        <input
          id="chat-input"
          class="..."
          placeholder="Message"
          maxlength="500"
          type="text" />
        <button
          type="button"
          id="submit-chat"
          class="...">Send</button>
      </div>
    </div>
  </div>

</div>

当DOM准备就绪时,我们将在全屏按钮中添加一个点击处理程序以调用toggleFullscreen()方法。

document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('fullscreen-toggle-btn')
    .addEventListener('click', toggleFullScreen);
});

toggleFullscreen()将包装<div>切换到全屏模式中。请注意,如果不可用标准requestFullscreen()方法,我们正在考虑各种浏览器实现。

const toggleFullScreen = async () => {
  const container = document.getElementById('video-chat-container');
  const fullscreenApi = container.requestFullscreen
    || container.webkitRequestFullScreen
    || container.mozRequestFullScreen
    || container.msRequestFullscreen;
  if (!document.fullscreenElement) {
    fullscreenApi.call(container);
  }
  else {
    document.exitFullscreen();
  }
};

在这一点上,按钮将按照我们的期望切换包装<div>,但看起来不会很好。

Fullscreen mode without styles

在全屏上应用样式

那么,我们怎么能使这个看起来更干净?好吧,我们可以通过解决<video>标签开始。它仍然被困在16x9的比率上,所以让它填充整个视图高度和宽度。

#video-chat-container:fullscreen video {
  height: 100vh;
  width: 100vw;
}

提醒:如上所述,:fullscreen伪级在大多数浏览器中都可以使用,但是:-webkit-full-screen必须在Safari中使用。这些声明无法合并,因此您会注意到Codepen中的“重复”规则以说明Safari。

并将固定定位应用于包含状态指示器和我们的手动全屏按钮的顶部覆盖层和自定义播放控件的底部覆盖。

#video-chat-container:fullscreen #top-overlay,
#video-chat-container:fullscreen #bottom-overlay {
  position: fixed;
}

Chat Div在透明背景下看起来更好。我们还将其限制为400px宽。

#video-chat-container:fullscreen #chat {
  background-color: rgba(0, 0, 0, 0.3);
  max-width: 400px;
  width: 400px;
}

让我们不要忘记移动用户。我们将在较小的显示器上使用媒体查询将该宽度更改为200px。

@media (max-width: 575.98px) {
  #video-chat-container:fullscreen #chat {
    max-width: 200px;
    width: 200px;
  }
  #video-chat-container:fullscreen #chat-input-container {
    width: 200px !important;
  }
}

575.98px?这似乎是用于移动断点的怪异价值。该值是从Bootstrap借用的,用于跨浏览器兼容性,以解决Safari问题。阅读有关here的更多信息。

对于包裹聊天div和聊天输入控件的聊天容器,让我们将其归于当前视图高度的80%,垂直居中,并使文本变为白色。

#video-chat-container:fullscreen #chat-container {
  height: 80vh;
  position: fixed;
  top: calc(50vh - (80vh / 2));
  right: 10px;
  color: #ffffff;
}

最后,我们将更改聊天文本输入,并提交按钮也具有白色边框和白色文字。

#video-chat-container:fullscreen #chat-input,
#video-chat-container:fullscreen #submit-chat{
  background: rgba(0,0,0,0.3);
  color: #ffffff;
  border: 1px solid rgb(var(--bs-white-rgb));
}

最终结果看起来不错。

Fullscreen video and chat overlay

聊天在视频中覆盖时仍然可以与聊天进行交互,并且以不会过分掩盖基础视频的方式呈现。

概括

在这篇文章中,我们学会了如何使用HTML全屏API和:fullscreen CSS伪级,为实时流动视图提供了改进的用户体验。我们在这里学到的只是一个起点。随意修改课程并创建自己引人入胜的实时流媒体体验。如果您有任何疑问,请在Twitter上发表评论或与我联系。