如何使用 HTML5 WebRTC 录制和保存视频
Posted
技术标签:
【中文标题】如何使用 HTML5 WebRTC 录制和保存视频【英文标题】:How to record and save video using HTML5 WebRTC 【发布时间】:2019-05-10 12:49:07 【问题描述】:首先运行代码 sn -p 然后阅读描述... 它会给你结构
我想在第二个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>
------------ 修改并解决问题
我在这里所做的,在Luis Estevez 代码中,我在startRecording
方法中声明了该事件,因为当我尝试在blob-array 中推送流块时,它响应错误:推送方法不存在,甚至我在声明一个数组后创建了一个对象数组。
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 :)
【问题讨论】:
这在移动浏览器中不起作用有什么建议吗? @ChhaiyaHarshad 对不起,我没有经历过这样的经历。任何人都可以帮助他吗?使用代码 sn-p 发布您的问题,可能有人可以用有效的解决方案回复您。 感谢您的重播。根据您的示例,我截取了相同的代码。但它不适用于移动浏览器。 @Luis Estevez 如果您对此有任何想法或建议,请告诉我。 完成。它正在工作。 @WasiF 我在录音中有另一个问题。声音干扰太多。你有什么建议吗? @ChhaiyaHarshad 我没有确切的解决方案,但我认为您需要使用某种语音修复库,因为据我所知 WebRTC 不提供此类功能。如果他们有改善声音的选项,您可以确认他们的文档。 【参考方案1】:您并没有“真正”记录流,您只是复制了流对象,而不是来自流的事件数据。
使用MediaRecorder
并将流作为构造函数参数传递。从事件处理程序 ondataavailable 中获取视频 blob。将记录的 blob 数组加入新的 Blob。从那里您可以使用createObbjectURL(blob);
获取网址
下面的sn-p是伪代码:
** typescript 无法识别“MediaRecorder”,因此您必须找到一种方法将 type any 添加到 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);
)
【讨论】:
感谢您的回复,我正在尝试实施您提供的解决方案,但面临一些问题,即 MediaStream 的每个事件调用,null
已经创建的对象,如handleDataAvailable
事件,我在类构造函数中声明如this.recordedBlobs = new Array<Blob>()
,但此事件使this.recordedBlobs
未定义。
handleDataAvailable 将来自 mediaRecorder.ondataavaiable 的 blob 推送到 recordedBlobs
。记录的Blobs 永远不应该是未定义的。我们只使用this.recordedBlobs = new Array<Blob>();
为其分配了一次值,并且它不应该在事件handleDataAvailable
中。您可以将您尝试的新代码添加到问题的底部吗?
@WasiF 添加我写的 console.log(s) 然后显示日志。
我猜您尝试将数据推送到一个确实存在的数组。你在处理数据事件之前分配了his.recordedBlobs = new Array<Blob>()
吗?
你能告诉如何录屏吗?我试过facingMode: 'screen'
,mediaSource: "screen"
,但没有成功。【参考方案2】:
在 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
浏览器。
祝你有美好的一天
【讨论】:
我试过你的代码。但它不工作。出现错误:无法读取未定义的属性“nativeElement”。你能帮帮我吗? @ManeeshRao 将该代码放入ngAfterViewInit
方法中,看起来它在其 html 呈现之前已被读取。
我已经添加了代码。 navigator.mediaDevices.getUserMedia( video: true, audio: true, ) 但是得到很多回声噪声?有什么建议吗?
我无法录制音频。它只是录制视频。
对不起,我不知道。我不能再继续这个项目了。以上是关于如何使用 HTML5 WebRTC 录制和保存视频的主要内容,如果未能解决你的问题,请参考以下文章