首先运行代码段,然后阅读说明... 它将为您提供结构
我想在第二个video element
中录制,播放和保存视频。我面临的问题是:流在第一个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()
}
}
我在这里所做的工作,在Luis Estevez代码中,我在startRecording
方法中声明了该事件,因为当我尝试在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)
}
谢谢Luis Estevez :)
答案 0 :(得分:3)
您没有“真正”记录流,只是复制了流对象,而不是来自流的事件数据。
使用MediaRecorder
并将流作为构造函数参数传递。从事件处理程序ondataavailable上获取视频 blob 。将记录的Blob数组连接到新的Blob。从那里可以使用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);
})
}
答案 1 :(得分:0)
@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)
}
}
}
<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
浏览器。
祝你有美好的一天