如何选择当前正在播放的 MediaStreamTrack?

How to pick which MediaStreamTrack is currently playing?

我有一个 MediaStream,带有 1 个音轨和 2 个视频轨。此流是通过将来自 navigator.mediaDevices.getUserMedia 的音频和视频轨道与来自 navigator.mediaDevices.getDisplayMedia 的视频轨道相结合而创建的。

var camStream = await navigator.mediaDevices.getUserMedia({audio: true, video: true, width: "1280"});
var screenStream = await navigator.mediaDevices.getDisplayMedia({video: true, width: "1280"});
var screenTrack = screenStream.getVideoTracks()[0];

camStream.addTrack(screenTrack);

此时,camStream有1个音轨和2个视频轨。

我有一个 HTML 元素 <video id="local-video"></video>,我通过设置 srcObject 属性使用它来播放流:

document.getElementById("local-video").srcObject = camStream;

问题是我无法选择正在播放的曲目。 camStream 视频轨道始终在 screenStream 视频轨道之上播放。 有没有一种方法可以将两个视频轨道都保留在流中,但选择视频元素中当前正在播放的一个?

到目前为止,唯一可行的是从流中删除一个视频轨道,以便另一个视频轨道可以播放,但我想将两个视频轨道都保留在流中,以便我可以切换 b/w他们。

MediaElement.videoTracks and MediaElement.audioTracks 应该是解决这个问题的通用方法,但是直到今天,浏览器支持仍然不是很好,因为没有浏览器真正正式支持它,none 完全支持 MediaStreams。 .

所以下面是一个片段,展示了它应该如何,但这是未来的事。

const vid = document.querySelector("video");
const btn = document.querySelector("button");
const track1 = makeVideoTrack("red");
const track2 = makeVideoTrack("blue");

const stream = new MediaStream([track1, track2]);
vid.srcObject = stream;

btn.onclick = () => {
  // setting one track to selected will unselect the previously selected one
  // so we need to grab the current state to switch it
  const state = vid.videoTracks[0].selected;
  vid.videoTracks[1].selected = state;
  vid.videoTracks[0].selected = !state;
};

function makeVideoTrack(color) {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  ctx.fillStyle = color;
  let x = 0;
  const anim = () => {
    x = (x + 1) % canvas.width;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillRect(x-5, 0, 10, canvas.height);
    requestAnimationFrame( anim );
  };
  anim();
  return canvas.captureStream().getVideoTracks()[0];
}
<video controls autoplay muted></video>

<button>switch video track</button>

今天,在您可以访问 MediaStream 的情况下,可以做的是构建一个仅包含您想要的 videoTrack 的新 MediaStream。 (人们可能会想重新排序这些曲目,但这只适用于当前的 Chrome 和 Firefox,specs 明确表示我们不应该依赖这种行为)

const vid = document.querySelector("video");
const btn = document.querySelector("button");
const tracks = [makeVideoTrack("red"), makeVideoTrack("blue")];
let selected_index = 0;
vid.srcObject = new MediaStream([ tracks[selected_index] ]);

btn.onclick = () => {
  selected_index = (selected_index + 1) % tracks.length
  vid.srcObject = new MediaStream([ tracks[selected_index] ]);
};

function makeVideoTrack(color) {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  ctx.fillStyle = color;
  let x = 0;
  const anim = () => {
    x = (x + 1) % canvas.width;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillRect(x-5, 0, 10, canvas.height);
    requestAnimationFrame( anim );
  };
  anim();
  return canvas.captureStream().getVideoTracks()[0];
}
<video controls autoplay muted></video>

<button>switch video track</button>