Re: [mediacapture-main] Width and height of MediaStreamTrack (#647)

Load this plnkr https://plnkr.co/edit/Axkb8s?preview&p=preview, substitute the below HTML for index.html. Run the code at least twice to 10 times in succession. 

At Chromium 80 

Expected output (result of `MediaRecorder` recording `MediaStream` from WebRTC)

```
resulting video resize 768 576
resulting video resize 480 240
resulting video resize 640 360
resulting video resize 400 300
resulting video resize 1280 720
```

occasional output

```
resulting video resize 288 216
resulting video resize 384 288
resulting video resize 480 240
resulting video resize 640 360
resulting video resize 400 300
resulting video resize 1280 720
```

At Firefox 70, Nightly 72 the code requires changing to an appreciable degree due to lack of full support for `AudioWorklet`. Occasionally the output at Firefox, Nightly will also have unexpected values

```
720 576 
480 240 
640 360  
400 300  
1280 720
```

```
<!DOCTYPE html>
<html>

<head>
 <title>
  Record MediaStream potentially including variable width and height
  MediaStreamTrack
 </title>
</head>

<body>
 <video id="video" autoplay controls></video>
 <script type="module">
  // MediaStream outputting #000000 video frames and audio silence
      import { mediaStream, audioContext, worker } from './export.js';
      let recorder, result;
      const videoStream = document.getElementById('video');
      console.log(mediaStream, audioContext, worker);
      (async () => {
        let handleChromiumVideoElementMediaRecorderBug;
        const [audioTrack, videoTrack] = ['audio', 'video'].map(kind =>
          mediaStream
            .getTracks()
            .find(({ kind: trackKind }) => trackKind === kind)
        );
        const fromLocalPeerConnection = new RTCPeerConnection({sdpSemantics:"unified-plan"});
        const toLocalPeerConnection = new RTCPeerConnection({sdpSemantics:"unified-plan"});
        const fromConnection = new Promise(resolve =>
          fromLocalPeerConnection.addEventListener(
            'icecandidate',
            async e => {
              console.log('from', e);
              try {
                resolve(
                  toLocalPeerConnection.addIceCandidate(
                    e.candidate ? e.candidate : null
                  )
                );
              } catch (e) {
                console.error(e);
              }
            },
            {
              once: true,
            }
          )
        );
        const toConnection = new Promise(resolve =>
          toLocalPeerConnection.addEventListener(
            'icecandidate',
            async e => {
              console.log('to', e);
              try {
                resolve(
                  fromLocalPeerConnection.addIceCandidate(
                    e.candidate ? e.candidate : null
                  )
                );
              } catch (e) {
                console.error(e);
              }
            },
            {
              once: true,
            }
          )
        );
        fromLocalPeerConnection.addEventListener('negotiationneeded', e => {
          console.log(e);
        });
        toLocalPeerConnection.addEventListener('negotiationneeded', e => {
          console.log(e);
        });
        let tracks = new Promise(resolve => {
          let ids = mediaStream.getTracks().map(({ id }) => id),
            i = 0;
          toLocalPeerConnection.addEventListener(
            'track',
            ({ track, streams: [stream] }) => {
              if (ids.includes(track.id) && ++i === ids.length) {
                resolve(stream);
              }
            }
          );
        });
        
        // Add initial audio and video MediaStreamTrack to PeerConnection, pass initial MediaStream
        const {
          sender: audioSender,
          receiver: audioReceiver,
        } = fromLocalPeerConnection.addTransceiver(audioTrack, {
          streams: [mediaStream],
        });
        const {
          sender: videoSender,
          receiver: videoReceiver,
        } = fromLocalPeerConnection.addTransceiver(videoTrack, {
          streams: [mediaStream],
        });
        console.log(audioSender, videoSender, audioReceiver, videoReceiver);
        const offer = await fromLocalPeerConnection.createOffer();
        await toLocalPeerConnection.setRemoteDescription(offer);
        await fromLocalPeerConnection.setLocalDescription(
          toLocalPeerConnection.remoteDescription
        );
        const answer = await toLocalPeerConnection.createAnswer();
        await fromLocalPeerConnection.setRemoteDescription(answer);
        await toLocalPeerConnection.setLocalDescription(
          fromLocalPeerConnection.remoteDescription
        );
        const stream = await tracks;
        // video.srcObject = stream;

        // When MediaStream is not set as srcObject Blob at MediaRecorder
        // dataavailable event size is 0
        const urls = await Promise.all(
          [
            {
              src:
                'https://upload.wikimedia.org/wikipedia/commons/a/a4/Xacti-AC8EX-Sample_video-001.ogv',
              from: 0,
              to: 4,
            },
            {
              src:
                'https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=10,20',
              from: 10,
              to: 20,
            },
            {
              from: 55,
              to: 60,
              src:
                'https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4',
            },
            {
              from: 0,
              to: 5,
              src:
                'https://raw.githubusercontent.com/w3c/web-platform-tests/master/media-source/mp4/test.mp4',
            },
            {
              from: 0,
              to: 5,
              src:
                'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
            },
            {
              from: 0,
              to: 5,
              src:
                'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4',
            },
            {
              from: 0,
              to: 6,
              src:
                'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4#t=0,6',
            },
          ].map(async ({ from, to, src }) => {
            try {
              const request = await fetch(src);
              const blob = await request.blob();
              const blobURL = URL.createObjectURL(blob);
              const url = new URL(src);
              console.log(url.hash);
              return blobURL + (url.hash || `#t=${from},${to}`);
            } catch (e) {
              throw e;
            }
          })
        );
        //const videoStream = document.createElement("video");
        videoStream.muted = true;
        videoStream.onresize = e =>
          console.log(
            e.type,
            'every resize',
            e.target.videoWidth,
            e.target.videoHeight
          );
        videoStream.onloadedmetadata = e => {
          const { videoWidth, videoHeight } = e.target;
          console.log(e.type, videoWidth, videoHeight);
        };
        const ms = videoStream.captureStream();
        ms.onaddtrack = async e => {
          if (e.track.kind === 'audio') {
            await audioSender.replaceTrack(e.track);
          } else {
            await videoSender.replaceTrack(e.track);
            console.log(e.track.getSettings());
          }
        };
        for (const blobURL of urls) {
          await new Promise(resolve => {
            videoStream.addEventListener(
              'pause',
              async _ => {
                resolve();
              },
              {
                once: true,
              }
            );
            videoStream.addEventListener(
              'canplay',
              async _ => {
                if (!recorder) {
                  tracks = await tracks;
                  handleChromiumVideoElementMediaRecorderBug = document.createElement("video").srcObject = tracks;
                  recorder = new MediaRecorder(tracks, {
                    mimeType: 'video/webm',
                  });
                  recorder.onstart = _ => {
                    console.log(_.type);
                  };
                  result = new Promise(resolve => {
                    recorder.addEventListener(
                      'dataavailable',
                      ({ data }) => {
                        resolve(data);
                      },
                      {
                        once: true,
                      }
                    );
                  });
                  recorder.start();
                }
                await videoStream.play();
              },
              {
                once: true,
              }
            );
            videoStream.src = blobURL;
          });
        }
        recorder.stop();
        let blob = await result;
        let blobURL = URL.createObjectURL(blob);
        console.log(blob);
        await audioContext.close();
        worker.terminate();
        [mediaStream.getTracks(), stream.getTracks(), ms.getTracks()]
          .flat()
          .forEach(track => {
            track.enabled = false;
            track.stop();
            console.log(track);
          });
        video.srcObject = null;
        video.remove();
        videoStream.src = '';
        videoStream.remove();
        const recordedVideo = document.createElement('video');
        document.body.appendChild(recordedVideo);
        recordedVideo.autoplay = recordedVideo.controls = true;
        recordedVideo.onresize = ({ target: { videoWidth, videoHeight } }) => {
          console.log("resulting video resize", videoWidth, videoHeight);
        };
        recordedVideo.src = blobURL;
      })();
    </script>
</body>

</html>
```

-- 
GitHub Notification of comment by guest271314
Please view or discuss this issue at https://github.com/w3c/mediacapture-main/issues/647#issuecomment-560247873 using your GitHub account

Received on Monday, 2 December 2019 06:10:36 UTC