您现在的位置是:网站首页> HTML&JS

开发库收集及使用

  • HTML&JS
  • 2025-01-31
  • 582人已阅读
摘要

开发库收集及使用


使用flv.js做直播

如何利用 `ffmpeg.js` 实现绿幕抠像播放

在H5页面如何将获得流手动喂给video元素

一款优雅的 HTML5 视频/音频播放器

优质的前端框架amis适合后端人员使用

可视化配置工具amis-editor-demo

DPlayer 播放RTMP

在线富文本编辑器wangEditor

阿里达摩院前端开源ChatUI

chatUI Pro开发智能聊天工具

jointJS 流程图绘制库

three.js在线教程

OpenCV.js 快速入门指南

Markdown 是一种轻量级的标记语言



使用flv.js做直播

为什么要在这个时候探索flv.js做直播呢?原因在于各大浏览器厂商已经默认禁用Flash,之前常见的Flash直播方案需要用户同意使用Flash后才可以正常使用直播功能,这样的用户体验很致命。

点击查看flv.js源码

常见直播协议

RTMP: 底层基于TCP,在浏览器端依赖Flash。

HTTP-FLV: 基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV。

WebSocket-FLV: 基于WebSocket传输FLV,依赖浏览器支持播放FLV。WebSocket建立在HTTP之上,建立WebSocket连接前还要先建立HTTP连接。

HLS: Http Live Streaming,苹果提出基于HTTP的流媒体传输协议。HTML5可以直接打开播放。

RTP: 基于UDP,延迟1秒,浏览器不支持。


在支持浏览器的协议里,延迟排序是:

RTMP = HTTP-FLV = WebSocket-FLV < HLS

而性能排序恰好相反:

RTMP > HTTP-FLV = WebSocket-FLV > HLS

也就是说延迟小的性能不好。


flv.js 简介

flv.js是来自Bilibli的开源项目。它解析FLV文件喂给原生HTML5 Video标签播放音视频数据,使浏览器在不借助Flash的情况下播放FLV成为可能。


flv.js 优势

由于浏览器对原生Video标签采用了硬件加速,性能很好,支持高清。

同时支持录播和直播

去掉对Flash的依赖


flv.js 原理

flv.js只做了一件事,在获取到FLV格式的音视频数据后通过原生的JS去解码FLV数据,再通过Media Source Extensions API 喂给原生HTML5 Video标签。(HTML5 原生仅支持播放 mp4/webm 格式,不支持 FLV)


flv.js 为什么要绕一圈,从服务器获取FLV再解码转换后再喂给Video标签呢?原因如下:

兼容目前的直播方案:目前大多数直播方案的音视频服务都是采用FLV容器格式传输音视频数据。

FLV容器格式相比于MP4格式更加简单,解析起来更快更方便。


搭建音视频服务

主播推流到音视频服务,音视频服务再转发给所有连接的客户端。为了让你快速搭建服务推荐我用go语言实现的livego,因为它可以运行在任何操作系统上,对Golang感兴趣?请看Golang 中文学习资料汇总。

下载livego,注意选对你的操作系统和位数。

解压,执行livego,服务就启动好了。它会启动RTMP(1935端口)服务用于主播推流,以及HTTP-FLV(7001端口)服务用于播放。


实现播放页

在react体系里使用react flv.js 组件reflv 快速实现。

先安装npm i reflv,再写代码:

import React, { PureComponent } from 'react';

import Reflv from 'reflv';


export class HttpFlv extends PureComponent {

  render() {

    return (

      <Reflv

        url={`http://localhost:7001/live/test.flv`}

        type="flv"

        isLive

        cors

      />

    )

  }

}


flv.js延迟优化

按照上面的教程运行起来的直播延迟大概有3秒,经过优化可以到1秒。在教你怎么优化前先要介绍下直播运行流程:


主播端在采集到一段时间的音视频原数据后,因为音视频原数据庞大需要先压缩数据:


通过H264视频编码压缩数据数据

通过PCM音频编码压缩音频AAC数据

压缩完后再通过FLV容器格式封装压缩后的数据,封装成一个FLV TAG


再把FLV TAG通过RTMP协议推流到音视频服务器,音视频服务器再从RTMP协议里解析出FLV TAG。


音视频服务器再通过HTTP协议通过和浏览器建立的长链接流式把FLV TAG传给浏览器。


flv.js 获取FLV TAG后解析出压缩后的音视频数据喂给Video播放。


知道流程后我们就知道从哪入手优化了:


主播端采集时收集了一段时间的音视频原数据,它专业的叫法是GOP。缩短这个收集时间(也就是减少GOP长度)可以优化延迟,但这样做的坏处是导致视频压缩率不高,传输效率低。

关闭音视频服务器的I桢缓存可以优化延迟,坏处是用户看到直播首屏的时间变大。

减少音视频服务器的buffer可以优化延迟,坏处是音视频服务器处理效率降低。

减少浏览器端flv.js的buffer可以优化延迟,坏处是浏览器端处理效率降低。

浏览器端开启flv.js的Worker,多线程运行flv.js提升解析速度可以优化延迟,这样做的flv.js配置代码是:

{

          enableWorker: true,

          enableStashBuffer: false,

          stashInitialSize: 128,// 减少首桢显示等待时长

}

这里是优化后的完整代码

import React, { PureComponent } from 'react';

import Reflv from '../../src/index';

import { HOST } from './index';


export class HttpFlv extends PureComponent {


  render() {

    return (

      <Reflv

        url={`http://${HOST}:7001/live/${this.props.id}.flv`}

        type="flv"

        isLive

        cors

        config={{

          enableWorker: true,

          enableStashBuffer: false,

          stashInitialSize: 128,

        }}

      />

    )

  }

}



如何利用 `ffmpeg.js` 实现绿幕抠像播放


<!DOCTYPE html>

<html>


<head>

  <meta charset="UTF-8">

  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>绿幕抠像播放示例</title>

</head>


<body>

  <video id="outputVideo" controls></video>


  <script src="ffmpeg.min.js"></script>

  <script>

    // 选择要处理的绿幕视频文件

    const inputFile = document.getElementById('yourFileInput').files[0];


    // 配置抠像参数

    const greenScreenColor = {

      hue: [100, 150],  // 绿色的色相范围

      saturation: [50, 100],  // 饱和度范围

      luminance: [50, 100]  // 亮度范围

    };


    // 初始化 ffmpeg

    const ffmpeg = createFFmpeg({

      corePath: 'ffmpeg-core.js',

      log: true

    });


    (async () => {

      await ffmpeg.load();


      ffmpeg.FS('writeFile', 'input.mp4', await new Response(inputFile).arrayBuffer());


      await ffmpeg.run('-i', 'input.mp4', '-vf', `chromakey=h=${greenScreenColor.hue[0]}-${greenScreenColor.hue[1]}:s=${greenScreenColor.saturation[0]}-${greenScreenColor.saturation[1]}:l=${greenScreenColor.luminance[0]}-${greenScreenColor.luminance[1]}`, 'output.mp4');


      const data = ffmpeg.FS('readFile', 'output.mp4');

      const url = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));


      document.getElementById('outputVideo').src = url;

    })();

  </script>

</body>


</html>



在H5页面如何将获得流手动喂给video元素

处理分段获得的字节数组流。在这种情况下,我们可以使用MediaSource API来实现将分段的字节数组流喂给video元素。以下是具体的步骤和示例代码:


1.创建MediaSource对象:

const mediaSource = new MediaSource();

const video = document.querySelector('video');

video.src = URL.createObjectURL(mediaSource);


2.等待MediaSource打开,然后创建SourceBuffer:

mediaSource.addEventListener('sourceopen', sourceOpen);


function sourceOpen() {

  const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');

  // 注意: MIME类型和编解码器可能需要根据你的视频格式进行调整

}


3.定义一个函数来添加数据到SourceBuffer:

function appendBuffer(buffer) {

  if (sourceBuffer.updating || mediaSource.readyState !== 'open') {

    setTimeout(() => appendBuffer(buffer), 50);

    return;

  }

  sourceBuffer.appendBuffer(buffer);

}


4.当你收到字节数组时,将其添加到SourceBuffer:

// 假设你有一个函数来获取字节数组

function getNextChunk() {

  // 这里是获取下一个字节数组的逻辑

  return new Uint8Array([/* 字节数据 */]);

}


function processNextChunk() {

  const chunk = getNextChunk();

  if (chunk) {

    appendBuffer(chunk);

    // 处理下一个块

    setTimeout(processNextChunk, 0);

  } else {

    // 所有数据都已处理完毕

    mediaSource.endOfStream();

  }

}


// 开始处理数据

processNextChunk();

完整的示例代码如下:

const mediaSource = new MediaSource();

const video = document.querySelector('video');

video.src = URL.createObjectURL(mediaSource);


let sourceBuffer;


mediaSource.addEventListener('sourceopen', sourceOpen);


function sourceOpen() {

  sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');

  processNextChunk();

}


function appendBuffer(buffer) {

  if (sourceBuffer.updating || mediaSource.readyState !== 'open') {

    setTimeout(() => appendBuffer(buffer), 50);

    return;

  }

  sourceBuffer.appendBuffer(buffer);

}


function getNextChunk() {

  // 这里是获取下一个字节数组的逻辑

  // 返回 null 表示所有数据已经处理完毕

  return new Uint8Array([/* 字节数据 */]);

}


function processNextChunk() {

  const chunk = getNextChunk();

  if (chunk) {

    appendBuffer(chunk);

    // 处理下一个块

    setTimeout(processNextChunk, 0);

  } else {

    // 所有数据都已处理完毕

    mediaSource.endOfStream();

  }

}

这个方法允许你将分段获得的字节数组流喂给video元素。你需要根据实际情况调整MIME类型和编解码器,以及实现getNextChunk()函数来获取实际的字节数组数据。


请注意,这种方法要求你的字节数组必须是有效的MP4(或其他支持的格式)片段。如果你的数据不是标准的视频格式,可能需要先进行一些预处理或使用其他的方法来播放。


JS获得buffer组件Uint8Array的例子

function decodeImage() {

var oReq = new XMLHttpRequest();

oReq.open("GET", "demo_encode.png", true);

oReq.responseType = "arraybuffer";

oReq.onload = function (oEvent) {

var arrayBuffer = oReq.response; // 注意:不是oReq.responseText

if (arrayBuffer) {

var byteArray = new Uint8Array(arrayBuffer);

var decodeData = decode('KEY_HERE', byteArray);

document.getElementById("decodeJavaImage").src = URL.createObjectURL(

new Blob([decodeData], { type: 'image/png' })

);

}

};



一款优雅的 HTML5 视频/音频播放器

Plyr:https://github.com/sampotts/plyr

主要特性

多格式支持

HTML5 视频和音频

YouTube 视频

Vimeo 视频

支持直播流(HLS, Dash等)

功能丰富

支持字幕和画中画

支持倍速播放

支持预览缩略图

支持快捷键控制

支持全屏播放

支持清晰度切换

性能出色

轻量级,无依赖

原生 ES6 编写

支持 CDN 加速


快速开始

1. 安装

# NPM

npm install plyr



# 或者使用 CDN

<script src="https://cdn.plyr.io/3.7.8/plyr.js"></script>

<link rel="stylesheet" href="https://cdn.plyr.io/3.7.8/plyr.css">

2. HTML 结构

<!-- 视频播放器 -->

<video id="player" playsinline controls>

    <source src="/path/to/video.mp4" type="video/mp4" />

    <source src="/path/to/video.webm" type="video/webm" />

    

    <!-- 字幕可选 -->

    <track kind="captions" label="中文字幕" src="/path/to/captions.vtt" srclang="zh" default />

</video>



<!-- YouTube 播放器 -->

<div id="player">

    <iframe

        src="https://www.youtube.com/embed/bTqVqk7FSmY"

        allowfullscreen

        allowtransparency

        allow="autoplay"

    ></iframe>

</div>

3. JavaScript 初始化

const player = new Plyr('#player', {

    // 配置选项

    controls: [

        'play-large', 'play', 'progress', 

        'current-time', 'mute', 'volume', 

        'captions', 'settings', 'pip', 

        'airplay', 'fullscreen'

    ]

});


高级功能展示

1. 清晰度切换

const player = new Plyr('#player', {

    quality: {

        default: 576,

        options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240]

    }

});

2. 预览缩略图

const player = new Plyr('#player', {

    previewThumbnails: {

        enabled: true,

        src: '/path/to/thumbnails.vtt'

    }

});

3. 自定义主题

:root {

    --plyr-color-main: #1ac266;

    --plyr-video-background: #000;

    --plyr-menu-background: rgba(255, 255, 255, 0.9);

}



DPlayer 播放RTMP

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>DPlayer</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css">

    <script src="https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js"></script>

</head>

<body>

    <div id="dplayer"></div>

    <script>

        const dp = new DPlayer({

            container: document.getElementById('dplayer'),

            video: {

                url: 'your rtmp url',

                type: 'rtmp'

            }

        });

    </script>

</body>

</html>



阿里达摩院前端开源ChatUI

点击进入ChatUI官网 ChatUI是阿里小蜜团队经过多年真实业务场景打磨和沉淀的对话式 UI 体系,致力于打造对话领域的设计和开发标准。在云上企业生态小范围内测半年之后,ChatUI 现已正式开源,期望与开发者共建和完善 ChatUI 体系,共同打造「让对话美而简单」的愿景

ChatUI 组件库基于以上设计原则进行设计,提供了50+组件,满足多样的对话场景需求,用户可基于基础组件搭建自己的对话界面,适合有深度定制需求的用户。

对于已经有对话接口,想开箱即用的用户,我们也贴心的提供了 ChatUI Pro,只需要在初始化的时候传入配置数据,即可快速生成可进行对话交互的界面。

通过 ChatUI Pro 你甚至都不需要前端知识就能配置出一个对话应用来,如果有前端基础的话也可以通过它强大的配置接口实现各种定制化需求。

<link rel="stylesheet" href="//g.alicdn.com/chatui/sdk-v2/0.1.1/sdk.css">

<script src="//g.alicdn.com/chatui/sdk-v2/0.1.1/sdk.js"></script>


<div id="root"></div>


<script>

  var bot = new ChatSDK({

    config: {

      navbar: {

        title: '智能助理'

      },

      robot: {

        avatar: '//gw.alicdn.com/tfs/TB1U7FBiAT2gK0jSZPcXXcKkpXa-108-108.jpg'

      },

      messages: [

        {

          type: 'text',

          content: {

            text: '智能助理为您服务,请问有什么可以帮您?'

          }

        }

      ]

    },

    requests: {

      send: function (msg) {

        return {

          url: '/api/ask',

          data: {

            q: msg.content.text

          }

        };

      }

    }

  });


  bot.run();



chatUI Pro开发智能聊天工具

<!DOCTYPE html>

<html>

<head>

    <meta name="renderer" content="webkit" />

    <meta name="force-rendering" content="webkit" />

    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

    <meta charset="UTF-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0, viewport-fit=cover" />

    <title>滴答小爱</title>

    <link rel="stylesheet" href="//g.alicdn.com/chatui/sdk-v2/0.2.4/sdk.css">

</head>

<body>

<div id="root"></div>

<script src="//g.alicdn.com/chatui/sdk-v2/0.2.4/sdk.js"></script>

<script src="//g.alicdn.com/chatui/extensions/0.0.7/isv-parser.js"></script>

<script src="js/setup.js"></script>

<script src="js/jquery-3.6.3.min.js"></script>

<script src="//g.alicdn.com/chatui/icons/0.3.0/index.js" async></script>

</body>

</html>

创建setup.js实现chatUI Pro与后端通信交换

var bot = new ChatSDK({

    config: {

        // navbar: {

        //     title: '滴答小爱'

        // },

        robot: {

            avatar: 'images/chat.png'

        },

        // 用户头像

        user: {

            avatar: 'images/user.png',

        },

        // 首屏消息

        messages: [

            {

                type: 'text',

                content: {

                    text: '您好,小爱为您服务,请问有什么可以帮您的?'

                }

            }

        ],

        // 快捷短语

        // quickReplies: [

        //     { name: '健康码颜色',isHighlight:true },

        //     { name: '入浙通行申报' },

        //     { name: '健康码是否可截图使用' },

        //     { name: '健康通行码适用范围' },

        // ],

        // 输入框占位符

        placeholder: '输入任何您想询问的问题',

    },

    requests: {

        send: function (msg) {

            if (msg.type === 'text') {

                return {

                    url: '/ask',

                    data: {

                        question: msg.content.text

                    }

                };

            }

        }

    },

    handlers: {

        /**

         *

         * 解析请求返回的数据

         * @param {object} res - 请求返回的数据

         * @param {object} requestType - 请求类型

         * @return {array}

         */

        parseResponse: function (res, requestType) {

            // 根据 requestType 处理数据

            if (requestType === 'send' && res.code==0) {

                // 用 isv 消息解析器处理数据

                $.ajaxSettings.async=false;

                var answer="";

                var isOK=false;

                while(!isOK){

                    $.get("/answer",{uuid:res.data},function(result){

                        console.log(result.data)

                        if(null != result.data){

                            isOK=true;

                            answer=result.data;

                        }

                    },"json");

                    if(!isOK){

                        sleep(5000);

                    }

                }

                $.ajaxSettings.async=true;

                return [{"_id":res.data,type:"text",content:{text:answer},position:"left"}];

            }

        },

    },

});

function sleep(n) { //n表示的毫秒数

    var start = new Date().getTime();

    while (true) {

        if (new Date().getTime() - start > n) {

            break;

        }

    }

}

bot.run();


OpenCV.js 快速入门指南

windows下安装emsdk

先从github上下载emsdk工程:


# Get the emsdk repo

git clone https://github.com/emscripten-core/emsdk.git


# Enter that directory

cd emsdk

git pull 更新到最新代码


clone 工程可以在 git bash here 命令行下:


执行下面的指令用cmd命令行:


更新完成后安装最新的emsdk,并配置全局的环境变量:


emsdk install --global latest


当安装完成配置好后执行激活:


emsdk activate latest


这里的emsdk 命令 其实就是一个emsdk.bat的批处理文件


emsdk.bat  install --global latest

1.png

激活:

1.png



配置环境变量:

1.png



 


测试是否安装成功:


 1.png

2.png

3.png

4.png

5.png

6.png

7.png 


成功后在浏览器中输入http://localhost:8080/hello.html就会在控制台看到输出的“Hello, world!”。



构建过程

安装Emscripten SDK

git clone https://github.com/juj/emsdk.git

cd emsdk

./emsdk install latest

./emsdk activate latest

source ./emsdk_env.sh

获取OpenCV

wget https://github.com/opencv/opencv/archive/3.4.1.zip

unzip 3.4.1.zip

cd opencv-3.4.1

# 将OpenCV编译为WASM版本

python ./platform/js/build_js.py build_wasm --build_wasm



1. 简介

OpenCV.js: OpenCV 的 JavaScript 版本

官方指南:OpenCV.js Tutorials

2. 下载

可通过如下链接下载到指定版本的预编译 opencv.js 文件

https://docs.opencv.org/{version}/opencv.js


比如下载 4.5.5 版本的 opencv.js 文件

https://docs.opencv.org/4.5.5/opencv.js


3. 安装使用

HTML script 标签引入

<!-- OpenCV.js 4.5.5 版本 -->

<script src='https://docs.opencv.org/4.5.5/opencv.js'></script>


node.js 使用


// 加载 OpenCV.js

function loadOpenCV(path) {

    return new Promise(resolve => {

        global.Module = {

            onRuntimeInitialized: resolve

        };

        global.cv = require(path);

    });

}


// 加载并创建一个图像

async function run(path){

    await loadOpenCV(path)

    let img = new cv.Mat()

    img.delete()

}


// 设置文件路径

const path = './opencv.js'


// 运行

run(path)


4. 数据类型

图像数据类型


Mat 是 OpenCV 基础的图像数据结构,其数据类型对照表如下:


Data Properties C++ Type JavaScript Typed Array Mat Type

data uchar Uint8Array CV_8U

data8S char Int8Array CV_8S

data16U ushort Uint16Array CV_16U

data16S short Int16Array CV_16S

data32S int Int32Array CV_32S

data32F float Float32Array CV_32F

data64F double Float64Array CV_64F

MatVector 即多个 Mat 组成的向量,使用 push_back(mat: cv.Mat)、 get(index: number) 和 set(index: number, mat: cv.Mat)方法添加、读取和设置 Mat 至 MatVector 中


Mat 和 MatVector 类型的变量请在不再需要使用的时候使用 delete() 方法将其删除,否则该变量将会持续占用内存


简单的创建和删除方式如下:


// 创建一个 Mat

let mat = new cv.Mat()


// 创建一个 MatVector

let matVector = new cv.MatVector()


// 添加一个 Mat

matVector.push_back(mat)


// 获取 index 为 0 的 Mat 

mat = matVector.get(0)


// 设置 index 为 0 的 Mat 

matVector.set(0, mat)


// 删除 Mat

mat.delete()


// 删除 MatVector

matVector.delete()


其他数据类型及其对应的 JS 对象格式,创建变量时两种方式均可使用


// 坐标点

new cv.Point(x, y) = {

    x: number, 

    y: number

}


// 像素点

new cv.Scalar(R, G, B, Alpha) = [

    R: number, 

    G: number, 

    B: number, 

    Alpha: number

]


// 图像尺寸

new cv.Size(width, height) = {

    width: number, 

    height: number

}


// 圆形区域

new cv.Circle(center, radius) = {

    center: {

        x: number,

        y: number

    }, 

    radius: number

}


// 矩形区域

new cv.Rect(x, y, width, height) = {

    x: number, 

    y: number, 

    width: number, 

    height: number

}


// 旋转矩形区域

new cv.RotatedRect(center, size, angle) = {

    center: {

        x: number,

        y: number

    }, 

    size: {

        width: number, 

        height: number 

    },

    angle: number

}


5. API

OpenCV.js 的 API 与 OpenCV C++ 版本 API 非常相似


OpenCV.js 常用的 API 如下:


图像读取和显示


// 读取

cv.imread(dom) -> dst


// 显示

cv.imshow(dst, dom)


  dom(Dom/string): img 标签或其 id(读取) / canvas 标签或其 id(读取/显示)


  dst(cv.Mat): 图像(RGBA)


创建图像


// 创建一个 Mat 格式的图像

new cv.Mat() -> mat

new cv.Mat(size, type) -> mat

new cv.Mat(rows, cols, type) -> mat

new cv.Mat(rows, cols, type, scalar) -> mat



// 创建一个值全部为零的图像

cv.Mat.zeros(rows, cols, type) -> mat


// 创建一个值全部为一的图像

cv.Mat.ones(rows, cols, type) -> mat


// 创建一个对角线值为一的图像

cv.Mat.eye(rows, cols, type) -> mat


// 使用 JS Array 生成图像

cv.matFromArray(rows, cols, type, array) -> mat


// 使用 canvas ImageData 生成图像

cv.matFromImageData(imgData) - mat


  size(cv.size): 图像尺寸

  rows(number): 图像高度

  cols(number): 图像宽度

  type(number): 图像类型(cv.CV_8UC3 ...)

  scalar(cv.Scalar): 图像初始值

  array(Array): JS 图像数组

  imgData(ImageData): canvas 图像数据


  mat(cv.Mat): 图像(type)


获取图像属性


// 图像高度

mat.rows -> rows


// 图像宽度

mat.cols -> cols


// 图像尺寸

mat.size() -> size


// 图像通道数量

mat.channels() -> channels


// 图像数据类型

mat.type() -> type


  mat(cv.Mat): 图像


  rows(number): 图像高度

  cols(number): 图像宽度

  size(cv.Size): 图像尺寸

  channles(number): 图像通道数量

  type(number): 图像数据类型(cv.CV_8UC3 ...)


获取图像数据


mat.data -> data

mat.data8S -> data8S

mat.data16U -> data16U

mat.data16S -> data16S

mat.data32S -> data32S

mat.data32F -> data32F

mat.data64F -> data64F


  mat(cv.Mat): 图像


  data(Uint8Array): 无符号 8 位整型数据

  data8S(Int8Array): 有符号 8 位整型数据

  data16U(Uint16Array): 无符号 16 位整型数据

  data16S(Int16Array): 有符号 16 位整型数据

  data32S(Int32Array): 有符号 32 位整型数据

  data32F(Float32Array): 32 位浮点数据

  data64F(Float64Array): 64 位浮点数据


裁切图像


mat.roi(rect) -> matROI


  rect(cv.Rect): 图像裁切区域


  matROI(cv.Mat): 裁切图像


颜色空间转换


cv.cvtColor(src, dst, code)


  src(cv.Mat): 输入图像

  dst(cv.Mat): 输出图像

  code(number): 转换类型(cv.COLOR_RGBA2RGB ...)


图像缩放


cv.resize(src, dst, dsize, fx, fy, interpolation)


  src(cv.Mat): 输入图像

  dst(cv.Mat): 输出图像

  dsize(cv.Size): 目标尺寸

  fx(number): x 轴缩放因子

  fy(number): y 轴缩放因子

  interpolation(number): 插值类型(cv.INTER_LINEAR ...)


创建图像向量


new cv.MatVector() -> matVector


  matVector(cv.MatVector): 图像向量


图像向量操作


// 添加

matVector.push_back(mat)


// 获取

matVector.get(index) -> mat


// 设置

matVector.set(index, mat)


  matVector(cv.MatVector): 图像向量


  mat(cv.Mat): 图像

  index(number): 索引值


通道拆分与合并


// 拆分

cv.split(src, channels)


// 合并

cv.merge(channels, dst)


  src(cv.Mat): 输入图像

  dst(cv.Mat): 输出图像

  channels(cv.MatVector): 通道图像向量


删除对象


// 删除图像对象

mat.delete()


// 删除图像向量对象

matVector.delete()


  mat(cv.Mat): 图像

  matVector(cv.MatVector): 图像向量


创建视频流


new cv.VideoCapture(videoSource) -> cap


  videoSource(Dom/string): video 标签或其 id


  cap(cv.VideoCapture): 视频流


读取视频帧


cap.read(mat)


  cap(cv.VideoCapture): 视频流


  mat(cv.Mat): 图像



一个使用Opencv.js的页面

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>Hello OpenCV.js</title>

</head>

<body>

<h2>Hello OpenCV.js</h2>

<p id="status">OpenCV.js is loading...</p>

<div>

  <div class="inputoutput">

    <img id="imageSrc" alt="No Image" />

    <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div>

  </div>

  <div class="inputoutput">

    <canvas id="canvasOutput" ></canvas>

    <div class="caption">canvasOutput</div>

  </div>

</div>

<script type="text/javascript">

let imgElement = document.getElementById('imageSrc');

let inputElement = document.getElementById('fileInput');

inputElement.addEventListener('change', (e) => {

  imgElement.src = URL.createObjectURL(e.target.files[0]);

}, false);

imgElement.onload = function() {

  let mat = cv.imread(imgElement);

  cv.imshow('canvasOutput', mat);

  mat.delete();

};

function onOpenCvReady() {

  document.getElementById('status').innerHTML = 'OpenCV.js is ready.';

}

</script>

<script async src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>

</body>

</html>


构建过程

安装Emscripten SDK

git clone https://github.com/juj/emsdk.git

cd emsdk

./emsdk install latest

./emsdk activate latest

source ./emsdk_env.sh

获取OpenCV

wget https://github.com/opencv/opencv/archive/3.4.1.zip

unzip 3.4.1.zip

cd opencv-3.4.1

# 将OpenCV编译为WASM版本

python ./platform/js/build_js.py build_wasm --build_wasm


Markdown 是一种轻量级的标记语言

点击在线查看

Markdown 最全语法指南

开源在线Markdown编辑器(https://github.com/pandao/editor.md)

点击查看使用例子

Download & install

Download:

Github download


NPM install :

npm install editor.md


Bower install :

bower install editor.md


Usages

Create a Markdown editor

<link rel="stylesheet" href="editor.md/css/editormd.min.css" />

<div id="editor">

    <!-- Tips: Editor.md can auto append a `<textarea>` tag -->

    <textarea style="display:none;">### Hello Editor.md !</textarea>

</div>

<script src="jquery.min.js"></script>

<script src="editor.md/editormd.min.js"></script>

<script type="text/javascript">

    $(function() {

        var editor = editormd("editor", {

            // width: "100%",

            // height: "100%",

            // markdown: "xxxx",     // dynamic set Markdown text

            path : "editor.md/lib/"  // Autoload modules mode, codemirror, marked... dependents libs path

        });

    });

</script>


Markdown to HTML

<link rel="stylesheet" href="editormd/css/editormd.preview.css" />

<div id="test-markdown-view">

    <!-- Server-side output Markdown text -->

    <textarea style="display:none;">### Hello world!</textarea>             

</div>

<script src="jquery.min.js"></script>

<script src="editormd/editormd.js"></script>

<script src="editormd/lib/marked.min.js"></script>

<script src="editormd/lib/prettify.min.js"></script>

<script type="text/javascript">

    $(function() {

    var testView = editormd.markdownToHTML("test-markdown-view", {

            // markdown : "[TOC]\n### Hello world!\n## Heading 2", // Also, you can dynamic set Markdown text

            // htmlDecode : true,  // Enable / disable HTML tag encode.

            // htmlDecode : "style,script,iframe",  // Note: If enabled, you should filter some dangerous HTML tags for website security.

        });

    });

</script>   


Options

Editor.md options and default values:


{

    mode                 : "gfm",          // gfm or markdown

    name                 : "",             // Form element name for post

    value                : "",             // value for CodeMirror, if mode not gfm/markdown

    theme                : "",             // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty

    editorTheme          : "default",      // Editor area, this is CodeMirror theme at v1.5.0

    previewTheme         : "",             // Preview area theme, default empty

    markdown             : "",             // Markdown source code

    appendMarkdown       : "",             // if in init textarea value not empty, append markdown to textarea

    width                : "100%",

    height               : "100%",

    path                 : "./lib/",       // Dependents module file directory

    pluginPath           : "",             // If this empty, default use settings.path + "../plugins/"

    delay                : 300,            // Delay parse markdown to html, Uint : ms

    autoLoadModules      : true,           // Automatic load dependent module files

    watch                : true,

    placeholder          : "Enjoy Markdown! coding now...",

    gotoLine             : true,           // Enable / disable goto a line

    codeFold             : false,

    autoHeight           : false,

    autoFocus            : true,           // Enable / disable auto focus editor left input area

    autoCloseTags        : true,

    searchReplace        : true,           // Enable / disable (CodeMirror) search and replace function

    syncScrolling        : true,           // options: true | false | "single", default true

    readOnly             : false,          // Enable / disable readonly mode

    tabSize              : 4,

    indentUnit           : 4,

    lineNumbers          : true,           // Display editor line numbers

    lineWrapping         : true,

    autoCloseBrackets    : true,

    showTrailingSpace    : true,

    matchBrackets        : true,

    indentWithTabs       : true,

    styleSelectedText    : true,

    matchWordHighlight   : true,           // options: true, false, "onselected"

    styleActiveLine      : true,           // Highlight the current line

    dialogLockScreen     : true,

    dialogShowMask       : true,

    dialogDraggable      : true,

    dialogMaskBgColor    : "#fff",

    dialogMaskOpacity    : 0.1,

    fontSize             : "13px",

    saveHTMLToTextarea   : false,          // If enable, Editor will create a <textarea name="{editor-id}-html-code"> tag save HTML code for form post to server-side.

    disabledKeyMaps      : [],

    

    onload               : function() {},

    onresize             : function() {},

    onchange             : function() {},

    onwatch              : null,

    onunwatch            : null,

    onpreviewing         : function() {},

    onpreviewed          : function() {},

    onfullscreen         : function() {},

    onfullscreenExit     : function() {},

    onscroll             : function() {},

    onpreviewscroll      : function() {},

    

    imageUpload          : false,          // Enable/disable upload

    imageFormats         : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],

    imageUploadURL       : "",             // Upload url

    crossDomainUpload    : false,          // Enable/disable Cross-domain upload

    uploadCallbackURL    : "",             // Cross-domain upload callback url


    toc                  : true,           // Table of contents

    tocm                 : false,          // Using [TOCM], auto create ToC dropdown menu

    tocTitle             : "",             // for ToC dropdown menu button

    tocDropdown          : false,          // Enable/disable Table Of Contents dropdown menu

    tocContainer         : "",             // Custom Table Of Contents Container Selector

    tocStartLevel        : 1,              // Said from H1 to create ToC

    htmlDecode           : false,          // Open the HTML tag identification 

    pageBreak            : true,           // Enable parse page break [========]

    atLink               : true,           // for @link

    emailLink            : true,           // for email address auto link

    taskList             : false,          // Enable Github Flavored Markdown task lists

    emoji                : false,          // :emoji: , Support Github emoji, Twitter Emoji (Twemoji);

                                           // Support FontAwesome icon emoji :fa-xxx: > Using fontAwesome icon web fonts;

                                           // Support Editor.md logo icon emoji :editormd-logo: :editormd-logo-1x: > 1~8x;

    tex                  : false,          // TeX(LaTeX), based on KaTeX

    flowChart            : false,          // flowChart.js only support IE9+

    sequenceDiagram      : false,          // sequenceDiagram.js only support IE9+

    previewCodeHighlight : true,           // Enable / disable code highlight of editor preview area


    toolbar              : true,           // show or hide toolbar

    toolbarAutoFixed     : true,           // on window scroll auto fixed position

    toolbarIcons         : "full",         // Toolbar icons mode, options: full, simple, mini, See `editormd.toolbarModes` property.

    toolbarTitles        : {},

    toolbarHandlers      : {

        ucwords : function() {

            return editormd.toolbarHandlers.ucwords;

        },

        lowercase : function() {

            return editormd.toolbarHandlers.lowercase;

        }

    },

    toolbarCustomIcons   : {               // using html tag create toolbar icon, unused default <a> tag.

        lowercase        : "<a href=\"javascript:;\" title=\"Lowercase\" unselectable=\"on\"><i class=\"fa\" name=\"lowercase\" style=\"font-size:24px;margin-top: -10px;\">a</i></a>",

        "ucwords"        : "<a href=\"javascript:;\" title=\"ucwords\" unselectable=\"on\"><i class=\"fa\" name=\"ucwords\" style=\"font-size:20px;margin-top: -3px;\">Aa</i></a>"

    },

    toolbarIconTexts     : {},

    

    lang : {  // Language data, you can custom your language.

        name        : "zh-cn",

        description : "开源在线Markdown编辑器<br/>Open source online Markdown editor.",

        tocTitle    : "目录",

        toolbar     : {

            //...

        },

        button: {

            //...

        },

        dialog : {

            //...

        }

        //...

    }

















Top