Как записать и сохранить видео с помощью HTML5 WebRTC - PullRequest
0 голосов
/ 09 декабря 2018

Сначала запустите фрагмент кода, затем прочитайте описание ... Это даст вам структуру

Я хочу записывать, воспроизводить и сохранять видео во 2-й video element.Проблема, с которой я сталкиваюсь: поток запускается в 1-й video-element, но не может записать и сохранить видео

.video {
    border: 1px solid gray;
    box-shadow: 3px 4px lightgray;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>

<div style="text-align:center">
    <h1>Welcome to WebRTC</h1>
    <video class="video" #video autoplay controls></video>
    <video class="video" style="width:360;" autoplay controls #recordedVideo></video>
    <br>
    <button class="btn btn-warning" (click)="startRecording()">Start</button>
    <button class="btn btn-warning" (click)="stopRecording()">Stop</button>
    <button class="btn btn-warning" (click)="playRecording()">Play</button>
</div>
export class ScreenRecordComponent implements OnInit {

  @ViewChild('video') videoElementRef: ElementRef;
  @ViewChild('recordedVideo') recordVideoElementRef: ElementRef;

  recordMedia: MediaStream;
  videoElement: HTMLVideoElement
  recordVideoElement: HTMLVideoElement

  async ngOnInit() {
    this.videoElement = this.videoElementRef.nativeElement
    this.recordVideoElement = this.recordVideoElementRef.nativeElement

    navigator.mediaDevices.getUserMedia({ video: { width: 360 } }).then(stream => {
      this.videoElement.srcObject = stream
    })
  }

  async startRecording() {
    navigator.mediaDevices.getUserMedia({ video: { width: 360 } }).then(stream => {
      this.recordMedia = stream
      this.videoElement.srcObject = stream
    })
  }

  stopRecording() {
    this.recordVideoElement.srcObject = this.recordMedia
    this.recordMedia.getTracks().forEach(track => {
      track.stop()
    })
  }

  playRecording() {
    this.recordVideoElement.srcObject = this.recordMedia
    this.recordVideoElement.play()
  }

}

------------------------ Изменена и решена проблема

То, что я сделал здесь, в коде Луиса Эстевеса , я объявил событие там в методе startRecording, потому что когда я пытался протолкнуть stream-chunk в blob-массив, он ответил на ошибку: метод push не существует, даже я создал объект-массив после того, как объявил массив.

startRecording(stream) {
    let options = { mimeType: 'video/webm' }
    this.recordedBlobs = []
    console.log(this.recordedBlobs)
    try {
      this.mediaRecorder = new MediaRecorder(stream, options)
    } catch (e0) {
      console.log('Try different mimeType')
    }

    console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options)
    // this.mediaRecorder.onstop = this.handleStop
    this.mediaRecorder.onstop = (event) => {
      console.log('Recorder stopped: ', event)
      const videoBuffer = new Blob(this.recordedBlobs, { type: 'video/webm' })
      this.downloadUrl = window.URL.createObjectURL(videoBuffer) // you can download with <a> tag

      this.recordVideoElement = this.recordVideoElementRef.nativeElement
      this.recordVideoElement.src = this.downloadUrl
    }
    // this.mediaRecorder.ondataavailable = this.handleDataAvailable
    this.mediaRecorder.ondataavailable = (event) => {
      if (event.data && event.data.size > 0) {
        this.recordedBlobs.push(event.data)
      }
    }
    this.mediaRecorder.start(100) // collect 100ms of data
    console.log('MediaRecorder started', this.mediaRecorder)
  }
Спасибо Луис Эстевес :)

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Полный рабочий код для записи видео в формате Angular 6

RecordComponent.ts

  @ViewChild('recordedVideo') recordVideoElementRef: ElementRef
  @ViewChild('video') videoElementRef: ElementRef

  videoElement: HTMLVideoElement
  recordVideoElement: HTMLVideoElement
  mediaRecorder: MediaRecorder
  recordedBlobs: Blob[]
  isRecording: boolean = false
  downloadUrl: string
  stream: MediaStream

  constructor() {
  }

  async ngOnInit() {
    this.videoElement = this.videoElementRef.nativeElement
    this.recordVideoElement = this.recordVideoElementRef.nativeElement

    navigator.mediaDevices.getUserMedia({
      video: {
        width: 360
      }
    }).then(stream => {
      this.stream = stream
      this.videoElement.srcObject = this.stream
    })
  }

  startRecording() {
    this.recordedBlobs = []
    let options: MediaRecorderOptions = { mimeType: 'video/webm' }

    try {
      this.mediaRecorder = new MediaRecorder(this.stream, options)
    } catch (err) {
      console.log(err)
    }

    this.mediaRecorder.start() // collect 100ms of data
    this.isRecording = !this.isRecording
    this.onDataAvailableEvent()
    this.onStopRecordingEvent()
  }

  stopRecording() {
    this.mediaRecorder.stop()
    this.isRecording = !this.isRecording
    console.log('Recorded Blobs: ', this.recordedBlobs)
  }

  playRecording() {
    if (!this.recordedBlobs || !this.recordedBlobs.length) {
      console.log('cannot play.')
      return
    }
    this.recordVideoElement.play()
  }

  onDataAvailableEvent() {
    try {
      this.mediaRecorder.ondataavailable = (event: BlobEvent) => {
        if (event.data && event.data.size > 0) {
          this.recordedBlobs.push(event.data)
        }
      }
    } catch (error) {
      console.log(error)
    }
  }

  onStopRecordingEvent() {
    try {
      this.mediaRecorder.onstop = (event: Event) => {
        const videoBuffer = new Blob(this.recordedBlobs, { type: 'video/webm' })
        this.downloadUrl = window.URL.createObjectURL(videoBuffer) // you can download with <a> tag
        this.recordVideoElement.src = this.downloadUrl
      }
    } catch (error) {
      console.log(error)
    }
  }

}

RecordComponent.html

<div style="text-align:center">
    <h1>Welcome to WebRTC</h1>
    <video class="video" #video autoplay controls></video>
    <span class="m-1"></span>
    <video class="video" style="width:360 !important;" controls #recordedVideo></video>
    <br>
    <button class="btn btn-primary btn-lg" *ngIf="!isRecording" (click)="startRecording()">Start Recording</button>
    <button class="btn btn-warning btn-lg" *ngIf="isRecording" (click)="stopRecording()">Stop Recording</button>
  </div>

Примечание. Если вы получаете сообщение об ошибке, MediaRecorder не найден и т.д., затем выполните

npm i @types/dom-mediacapture-record

Обязательно обновите также браузер Chrome.

Хорошего дня

0 голосов
/ 09 декабря 2018

Вы не «действительно» записали поток, вы просто скопировали объект потока, а не данные о событии, поступающие из потока.

Используйте MediaRecorder и передайте потокв качестве аргумента конструктора.Захватите видео blob из обработчика событий по доступным данным.Присоедините записанный массив BLOB-объектов к новому BLOB-объекту.Оттуда вы можете получить URL, используя createObbjectURL(blob);

Следующий фрагмент кода является псевдокодом:

** машинопись не распознает MediaRecorder, поэтому вам нужно будет найти способ добавитьвведите любой в MediaRecorder


mediaRecorder: any;
recordedBlobs: Blob[];
downloadUrl: string;

handleDataAvailable(event) {
    if (event.data && event.data.size > 0) {
      this.recordedBlobs.push(event.data);
    }
}

handleStop(event) {
    console.log('Recorder stopped: ', event);
    const videoBuffer = new Blob(this.recordedBlobs, {type: 'video/webm'});
    this.downloadUrl = window.URL.createObjectURL(videoBuffer); // you can download with <a> tag
    this.recordVideoElement.src = this.downloadUrl;
}

startRecording(stream) {
    let options = {mimeType: 'video/webm'};
    this.recordedBlobs = [];
    try {
        this.mediaRecorder = new MediaRecorder(stream, options);
    } catch (e0) {
        console.log('Try different mimeType');
    }
    console.log('Created MediaRecorder', this.mediaRecorder, 'with options', options);
    this.mediaRecorder.onstop = this.handleStop;
    this.mediaRecorder.ondataavailable = this.handleDataAvailable;
    this.mediaRecorder.start(100); // collect 100ms of data
    console.log('MediaRecorder started', this.mediaRecorder);
}

stopRecording() {
  this.mediaRecorder.stop();
  console.log('Recorded Blobs: ', this.recordedBlobs);
  this.recordVideoElement.controls = true;
}

playRecording() {
  if (!this.recordedBlobs.length) {
      console.log('cannot play.');
      return;
  }
  this.recordVideoElement.play();
}

async ngOnInit() {
  navigator.mediaDevices.getUserMedia({ video: { width: 360 } }).then(stream => {
    this.videoElement.srcObject = stream
    this.startRecording(stream);
  })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...