Exemplos de captura e reprodução de áudio e vídeo WebRTC e análise de fluxo de mídia MediaStream

Exemplos de captura e reprodução de áudio e vídeo WebRTC e análise de fluxo de mídia MediaStream


Índice

  1. Código de amostra - abra a câmera e o microfone ao mesmo tempo, exiba a tela e reproduza o som capturado na página
  2. análise de API
    1. dispositivos de mídia
    2. Fluxo de mídia MediaStream

1. Código de amostra - abra a câmera e o microfone ao mesmo tempo, exiba a tela e reproduza o som capturado na página

  1. o código
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebRTC Demo</title>
</head>
<body>
<video id="local-video" autoplay playsinline></video>
<button id="showVideo">打开音视频</button>
</body>

<script>
    const constraints = {
    
    
        audio: true,
        video: {
    
    width: 640, height: 480}
    }

    // 处理打开摄像头成功
    function handleSuccess(mediaStream) {
    
    
        const video = document.querySelector("#local-video");
        video.srcObject = mediaStream;
    }

    // 异常处理
    function handleError(error) {
    
    
        console.error("getUserMedia error: " + error)
    }

    function onOpenAV(e) {
    
    
        navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
    }

    document.querySelector("#showVideo").addEventListener("click", onOpenAV)

</script>
</html>

  1. Efeito
    insira a descrição da imagem aqui

2. Análise de API

1. dispositivos de mídia

  1. mediaDevices é uma propriedade somente leitura do Navigator que retorna um objeto MediaDevices que fornece acesso de conexão a dispositivos de entrada de mídia, como câmeras e microfones, incluindo compartilhamento de tela.
  2. gramática:
var mediaDevices = navigator.mediaDevices;
  1. MediaDevices é um objeto singleton e os membros desse objeto podem ser usados ​​diretamente, por exemplo, chamando navigator.mediaDevices.getUserMedia().

2. Fluxo de mídia MediaStream

  1. navigator.mediaDevices.getUserMedia() solicitará ao usuário permissão para usar a entrada de mídia, e a entrada de mídia gerará um MediaStream (fluxo de mídia), que é o portador de informações e representa o fluxo de conteúdo de um dispositivo de mídia.
  2. Fluxos de mídia podem ser coletados, transmitidos e reproduzidos. Normalmente, um fluxo de mídia contém várias faixas de mídia, como faixas de áudio e faixas de vídeo.
  3. Os fluxos de mídia são gerenciados usando a interface MediaStream.Geralmente, existem várias maneiras de obter fluxos de mídia.
    a. Obtenha o objeto de transmissão da câmera ou do microfone.
    b. Obtenha o objeto de fluxo do compartilhamento de tela.
    c. Obtenha o objeto de fluxo do conteúdo da tela (HTMLCanvasElement).
    d. Obtenha o objeto de fluxo do elemento de mídia (HTMLMediaElement).
  4. Os fluxos de mídia obtidos pelos métodos acima podem ser transmitidos por meio do WebRTC e compartilhados entre vários pares.
  5. Retorne um objeto Promise e resolver chamará de volta um objeto MediaStream após o sucesso.
  6. Se o usuário negar a permissão ou a fonte de mídia necessária não estiver disponível, a promessa rejeitará e chamará de volta um PermissionDeniedError ou NotFoundError.
  7. Uso comum:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
    
    
  /* 使用这个 stream stream */
})
.catch(function(err) {
    
    
  /* 处理 error */
});
  1. Definição de MediaStream
interface MediaStream : EventTarget {
    
    
  constructor();
  constructor(MediaStream stream);
  constructor(sequence<MediaStreamTrack> tracks);
  readonly attribute DOMString id;
  sequence<MediaStreamTrack> getAudioTracks();
  sequence<MediaStreamTrack> getVideoTracks();
  sequence<MediaStreamTrack> getTracks();
  MediaStreamTrack? getTrackById(DOMString trackId);
  void addTrack(MediaStreamTrack track);
  void removeTrack(MediaStreamTrack track);
  MediaStream clone();
  readonly attribute boolean active;
  attribute EventHandler onaddtrack;
  attribute EventHandler onremovetrack;
};

1. Propriedade MediaStream

1. ativo somente leitura
  1. Retorna o estado do MediaStream, o tipo é Boolean, true significa que está ativo, false significa que está inativo.
2. id é somente leitura
  1. Retorna o UUID do MediaStream, o tipo é string e o comprimento é 36 caracteres.

2. Método MediaStream

1. Método addTrack(): adiciona uma nova faixa de mídia ao fluxo de mídia.
stream.addTrack(track);
参数:Track,媒体轨道,类型为MediaStreamTrack。
返回值:无。
2. método clone(): retorna uma cópia do fluxo de mídia atual, e a cópia tem um identificador diferente e exclusivo.
const newstream = stream.clone();
// sameId为false
const sameId = newstream.id === stream.id? true : false
参数:无。
返回值:一个新的媒体流对象。
3. Método getAudioTracks(): retorna uma matriz de objetos de rastreamento de mídia cujo tipo de mídia é áudio e cujo tipo de membro é MediaStreamTrack.
  1. Observe que a ordem da matriz é indeterminada e pode variar de chamada para chamada.
const mediaStreamTracks = mediaStream.getAudioTracks()
参数:无。
返回值:mediaStreamTracks,媒体轨道对象数组,如果当前媒体流没有音频轨道,则返回数组为空。
  1. Exemplo: use o método getUserMedia() para obter o fluxo de mídia contendo faixas de vídeo e áudio. Se a chamada for bem-sucedida, anexe o fluxo de mídia ao elemento < >, defina um cronômetro e chame o método getAudioTracks() para obter videotodos faixas de áudio após 5 segundos e, finalmente, pare de reproduzir a primeira faixa de áudio.
navigator.mediaDevices.getUserMedia({
    
    audio: true, video: true})
  .then(mediaStream => {
    
    
  document.querySelector('video').srcObject = mediaStream;
  // 5s后,停止播放第一个音频轨道
  setTimeout(() => {
    
    
    const tracks = mediaStream.getAudioTracks()
    tracks[0].stop()
  }, 5000)
})
4. Método getVideoTracks(): retorna uma matriz de objetos de rastreamento de mídia cujo valor de atributo kind é video e o tipo do objeto de rastreamento de mídia é MediaStream Track.
  1. Observe que a ordem dos objetos no array é indeterminada e pode variar de chamada para chamada.
const mediaStreamTracks = mediaStream.getVideoTracks()
参数:无。
返回值:mediaStreamTracks是媒体轨道对象数组。如果当前媒体流没有视频轨道,则返回数组为空。
  1. Exemplo: O método getUserMedia() obtém o fluxo de vídeo, se a chamada for bem-sucedida, anexe o fluxo de mídia ao videoelemento < > e, em seguida, obtenha a primeira faixa de vídeo e capture uma imagem da faixa de vídeo.
navigator.mediaDevices.getUserMedia({
    
    video: true})
  .then(mediaStream => {
    
    
  document.querySelector('video').srcObject = mediaStream;
  const track = mediaStream.getVideoTracks()[0];
  // 截取图片
  const imageCapture = new ImageCapture(track);
  return imageCapture;
})
5. Método getTrackById(): retorna o objeto track com o ID especificado.
  1. Se nenhum parâmetro for fornecido ou o valor do ID não corresponder, null será retornado; se houver várias faixas com o mesmo ID, o método retornará a primeira faixa correspondente.
const track = MediaStream.getTrackById(id);
参数:id,类型为字符串。
返回值:如果输入参数id与MediaStreamTrack.id匹配,则返回相应的MediaStream-Track对象,否则返回null
  1. Exemplo: obtenha a faixa de mídia com o ID especificado e aplique restrições para ajustar o volume para 0,5.
stream.getTrackById("primary-audio-track").applyConstraints({
    
     volume: 0.5 });
6. Método getTracks(): retorna um array de todos os objetos de trilha de mídia, incluindo todas as trilhas de vídeo e áudio.
  1. A ordem dos objetos no array é indeterminada e pode variar de chamada para chamada.
const mediaStreamTracks = mediaStream.getTracks()
参数:无。
返回值:媒体轨道对象数组。
  1. Use o método getUserMedia() para obter o fluxo que contém a faixa de vídeo. Se a chamada for bem-sucedida, anexe o fluxo ao videoelemento < >, defina o cronômetro, obtenha todas as faixas de mídia após 5 segundos e pare de reproduzir a primeira faixa de mídia (ou seja, a faixa de vídeo).
navigator.mediaDevices.getUserMedia({
    
    audio: false, video: true})
.then(mediaStream => {
    
    
  document.querySelector('video').srcObject = mediaStream;
  // 5s后,停止播放第一个媒体轨道
  setTimeout(() => {
    
    
    const tracks = mediaStream.getTracks()
    tracks[0].stop()
  }, 5000)
})

3. Evento MediaStream

1. evento addtrack: Este evento é acionado quando uma nova faixa de mídia (MediaStreamTrack) é adicionada, correspondendo ao manipulador de eventos onaddtrack
  1. Observe que esse evento só será acionado nas seguintes condições e não será acionado se o método MediaStream.addTrack() for chamado ativamente.
    1. Renegociação de RTCPeerConnection.
    2. HTMLMediaElement.captureStream() retorna uma nova faixa de mídia.
  2. Exemplo: quando uma nova faixa de mídia é adicionada ao fluxo de mídia, exiba o tipo e o rótulo da nova faixa de mídia.
// event类型为MediaStreamTrackEvent
// event.track类型为MediaStreamTrack
stream.onaddtrack = (event) => {
    
    
  let trackList = document.getElementById("tracks");
  let label = document.createElement("li");

  label.innerHTML = event.track.kind + ": " + event.track.label;
  trackList.appendChild(label);
};
  1. Além disso, você também pode usar o método addEventListener() para ouvir o evento addtrack.
2. evento removetrack: Este evento é acionado quando uma faixa de mídia é removida, correspondendo ao manipulador de eventos onremovetrack
  1. Observe que esse evento só será acionado nas seguintes situações e não será acionado se o método MediaStream.removeTrack() for chamado ativamente.
    1. Renegociação de RTCPeerConnection.
    2. HTMLMediaElement.captureStream() retorna uma nova faixa de mídia.
  2. Exemplo: Quando uma faixa de mídia é excluída de um fluxo de mídia, registre as informações da faixa de mídia.
// event类型为MediaStreamTrackEvent
// event.track类型为MediaStreamTrack
stream.onremovetrack = (event) => {
    
    
  let trackList = document.getElementById("tracks");
  let label = document.createElement("li");

  label.innerHTML = "Removed: " + event.track.kind + ": " + event.track.label;
  trackList.appendChild(label);
};
  1. Além disso, você também pode usar o método addEventListener() para ouvir o evento removetrack.

4. Restrições de parâmetros

  1. restrições, como um objeto MediaStreamConstraints, especifica o tipo de mídia solicitado e os parâmetros correspondentes.

  2. O parâmetro constraints é um objeto MediaStreamConstraints que contém dois membros, vídeo e áudio, para descrever o tipo de mídia solicitado.

    1. Pelo menos um tipo ou ambos devem ser especificados.
    2. Se o navegador não conseguir encontrar o tipo de mídia especificado ou não atender aos requisitos de parâmetro correspondentes, o objeto Promise retornado estará no estado rejeitado [com falha] e NotFoundError será usado como o parâmetro do retorno de chamada rejeitado [com falha].
  3. O seguinte solicita áudio e vídeo sem nenhum parâmetro:

{
    
     audio: true, video: true }
  1. Se true for definido para um determinado tipo de mídia, o fluxo resultante precisará ter esse tipo de faixa. Se um deles não puder ser obtido por algum motivo, getUserMedia() gerará um erro.

  2. Quando as informações da câmera e do microfone do usuário não podem ser acessadas por motivos de proteção de privacidade, o aplicativo pode usar o parâmetro de restrições adicionais para solicitar os recursos de câmera e microfone de que precisa ou deseja.

  3. O seguinte demonstra que o aplicativo deseja usar uma resolução de câmera de 1280x720:

{
    
    
  audio: true,
  video: {
    
     width: 1280, height: 720 }
}
  1. O navegador tentará atender a esse parâmetro de solicitação, mas se não puder atender com precisão aos requisitos de parâmetro nessa solicitação ou se o usuário optar por substituir o parâmetro na solicitação, ele poderá retornar outras resoluções.
  2. Ao forçar um tamanho específico, você pode usar as palavras-chave min, max ou exact (isto é, min == max).
  3. Os seguintes parâmetros indicam que é necessária uma resolução mínima de 1280x720.
{
    
    
  audio: true,
  video: {
    
    
    width: {
    
     min: 1280 },
    height: {
    
     min: 720 }
  }
}
  1. Se a câmera não suportar a resolução solicitada ou superior, o Promise retornado estará em estado rejeitado, NotFoundError será passado como parâmetro do retorno de chamada rejeitado e a autorização do usuário não será solicitada.
  2. A razão para o desempenho diferente é que, em comparação com o valor de solicitação simples e a palavra-chave ideal, as palavras-chave min, max e exact têm coercividade intrínseca, como:
{
    
    
  audio: true,
  video: {
    
    
    width: {
    
     min: 1024, ideal: 1280, max: 1920 },
    height: {
    
     min: 776, ideal: 720, max: 1080 }
  }
}
  1. Quando a requisição contém um valor ideal, este valor tem um peso maior, ou seja, o navegador tentará primeiro encontrar a configuração ou câmera (caso o dispositivo possua mais de uma câmera) que esteja mais próximo do valor ideal especificado.
  2. Um simples valor de requisição também pode ser entendido como um valor ideal para a aplicação, então nossa primeira requisição para especificar uma resolução também pode ser escrita da seguinte forma:
{
    
    
  audio: true,
  video: {
    
    
    width: {
    
     ideal: 1280 },
    height: {
    
     ideal: 720 }
  }
}
  1. Nem todas as restrições são números. Por exemplo, em um dispositivo móvel, o exemplo a seguir indica que a câmera frontal deve ser usada primeiro (se disponível):
{
    
     audio: true, video: {
    
     facingMode: "user" } }
  1. Para forçar o uso da câmera traseira, use:
{
    
     audio: true, video: {
    
     facingMode: {
    
     exact: "environment" } } }
  1. Em alguns casos, como ao usar um transporte de largura de banda limitada em WebRTC, uma taxa de quadros baixa pode ser mais apropriada.
{
    
     video: {
    
     frameRate: {
    
     ideal: 10, max: 15 } } };

5. Valor de retorno

var promise = navigator.mediaDevices.getUserMedia(constraints);
  1. Retorna um Promise, a função de retorno de chamada quando o Promise é bem-sucedido usa um objeto MediaStream como seu parâmetro.

6. Outliers

  1. Retorna um Promise em um estado de falha e a função de retorno de chamada após a falha do Promise usa um objeto DOMException como seu parâmetro. As possíveis exceções são:
  2. AbortError [erro de cancelamento]
    1. Embora o usuário e o sistema operacional tenham concedido acesso ao hardware do dispositivo e não haja problemas de hardware que gerem uma exceção NotReadableError, ainda existem alguns problemas que tornam o dispositivo inutilizável.
  3. NotAllowedError [erro negado]
    1. O usuário nega a solicitação de acesso da instância atual do navegador; ou o usuário nega o acesso da sessão atual; ou o usuário nega todas as solicitações de acesso à mídia globalmente.
    2. Versões mais antigas da especificação usavam SecurityError, mas SecurityError recebeu um novo significado em versões mais recentes.
  4. NotFoundError [Erro não encontrado]
    1. Não foi possível encontrar um tipo de mídia que satisfaça os parâmetros solicitados.
  5. NotReadableError[Não foi possível ler o erro]
    1. Embora o usuário tenha autorizado o uso do dispositivo correspondente, um erro de hardware, navegador ou nível da web no sistema operacional impede o acesso ao dispositivo.
  6. OverconstainedError[Erro de não atender aos requisitos]
    1. O requisito especificado não pode ser atendido pelo dispositivo. Essa exceção é um objeto do tipo OverconstainedError, que possui um atributo de restrição, que contém o objeto de restrição que não pode ser satisfeito no momento, e um atributo de mensagem, que contém uma string de fácil leitura para Explique a situação.
  7. NotFoundError [Erro não encontrado]
    1. Não foi possível encontrar um tipo de mídia que satisfaça os parâmetros solicitados.
  8. NotReadableError[Não foi possível ler o erro]
    1. Embora o usuário tenha autorizado o uso do dispositivo correspondente, um erro de hardware, navegador ou nível da web no sistema operacional impede o acesso ao dispositivo.
  9. OverconstainedError[Erro de não atender aos requisitos]
    1. O requisito especificado não pode ser atendido pelo dispositivo. Essa exceção é um objeto do tipo OverconstainedError, que possui um atributo de restrição, que contém o objeto de restrição que não pode ser satisfeito no momento, e um atributo de mensagem, que contém uma string de fácil leitura para Explique a situação.
  10. SecurityError [Erro de segurança]
    1. O uso de mídia do dispositivo está desabilitado no documento no qual getUserMedia() é chamado. A ativação ou desativação desse mecanismo depende das preferências individuais do usuário.
  11. TypeError [erro de tipo]
    1. O objeto de restrições não está definido como [nulo] ou ambos estão definidos como false.

Acho que você gosta

Origin blog.csdn.net/weixin_41910694/article/details/125502851
Recomendado
Clasificación