您现在的位置是:网站首页> HTML&JS
开发库收集及使用
- HTML&JS
- 2025-01-31
- 582人已阅读
开发库收集及使用
使用flv.js做直播
为什么要在这个时候探索flv.js做直播呢?原因在于各大浏览器厂商已经默认禁用Flash,之前常见的Flash直播方案需要用户同意使用Flash后才可以正常使用直播功能,这样的用户体验很致命。
常见直播协议
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
激活:
配置环境变量:
测试是否安装成功:
成功后在浏览器中输入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编辑器(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 : {
//...
}
//...
}
}
上一篇:Vue项目的创建运行及库
下一篇:浏览器JS常用技术收集