【问题标题】:Capturing the first video frame捕获第一个视频帧
【发布时间】:2020-04-30 02:00:30
【问题描述】:

我在 stackoverflow 中找到了很多关于如何捕获第一个视频图像帧的文章,但我看不出我在代码上做错了什么,使其无法正常工作。所以如果有人可以帮助我,非常感谢!

HTML 代码:

<ion-button expand="block" color="primary" (click)="onPickVideo()">
   <ion-icon name="videocam" slot="start"></ion-icon>
   <ion-label>Select video</ion-label>
 </ion-button>

  <input type="file" (change)="onFileChosen($event)" #filePicker/>

<div class="wrapper" *ngIf="flag">
  <video controls >
    <source [src]="videoDetail.dataString" type="video/mp4">
    unsupported video
  </video>
</div>

TS 代码:

import { Component, ViewChild, ElementRef } from '@angular/core';

export interface VideoDetail {
  ... Some code ...
}

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {

  ... Some code ...

  onPickVideo() {
    this.filePickerRef.nativeElement.click();
  }


  onFileChosen(ev: Event) {
    const files: FileList = (ev.target as HTMLInputElement).files;

  ... Some code ...      

    this.videoMetadataReader(this.videoBuffer, this.videoDetail);

    this.convertToDataString(this.videoBuffer, this.videoDetail);
  }

  // Metadata video reader
  videoMetadataReader(buffer: File, detail: VideoDetail) {
    const fileReader = new FileReader();
    this.videoBuffer = files[0];   // get video file

    fileReader.onload = () => {
      const blob = new Blob([fileReader.result], {type});

      const url = (URL || webkitURL).createObjectURL(blob);
      const video = document.createElement('video');  // create video element

      video.preload = 'metadata';                     // preload setting
      video.addEventListener('loadedmetadata', () => {

       ... Some code ...

        // Get first frame
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const img = new Image();


        canvas.height = video.videoHeight;
        canvas.width = video.videoWidth;

        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);


        img.src = canvas.toDataURL();
        detail.videoFrame = img.src;

        console.log('img :', img.src);

      });
      video.src = url; // start video load
    };
    fileReader.readAsArrayBuffer(buffer);
  }

  // File to dataUrl
  convertToDataString(buffer: File, detail: VideoDetail) {
    const fileReader = new FileReader();
    fileReader.onload = () => {
      const dataString = fileReader.result.toString();
      detail.dataString = dataString;
      this.flag = true;
    };
    fileReader.readAsDataURL(buffer);
  }
}

当我在 console.log 中看到 img 时,我得到一个图像,但完全是白色的,它不应该是白色的。

编辑以显示屏幕截图:红色为视频帧捕获,白色。

再次感谢您的帮助:)

编辑添加应用链接下载:

Download source code here

【问题讨论】:

  • 您确定您的设备确实支持视频编码格式吗?
  • 它在 chrome 上
  • 看起来视频没有完全加载。所以我只得到框架的一部分。有人知道我怎么知道视频已满载?
  • loadeddata 看起来像正确的事件:“媒体的第一帧已完成加载。”

标签: javascript html typescript ionic-framework ionic4


【解决方案1】:

我已经重现了您的问题:您应该将预加载类型从 preload 替换为 auto,并且将事件 loadedmetadata 更改为 loadeddatacanplay

顺便说一句,我使用下面的函数将 blob 转换为 dataUri(可以更改为异步或承诺):

function blobToDataURL(blob, callback) {
  var a = new FileReader();
  a.onload = function(e) {callback(e.target.result);}
  a.readAsDataURL(blob);
}

【讨论】:

  • 将预加载更改为自动时收到错误消息。 error TS2339: Property 'auto' does not exist on type 'HTMLVideoElement'.
  • 我已经编辑了问题以添加下载代码的链接
  • 你说的我明白了! video.preload = 'auto';video.addEventListener('loadeddata', () =&gt; {
  • 我已经用更正更新了 github 链接。您可以下载到工作代码。 @stck 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多