里云播放器SDK(ApsaraVideo for Player SDK)是阿里视频云端到云到端服务的重要一环,除了支持点播和直播的基础播放功能外,还深度融合视频云业务,支持视频的加密播放、安全下载、首屏秒开、低延时等业务场景,为用户提供简单、快速、安全、稳定的视频播放服务。本文衔接上文,详细介绍web播放器的功能及实现。
播放器架构
Aliplayer Web播放器分为H5和Flash两个,Flash播放器随着技术的发展会逐渐被边缘化,所以我们以后只做维护,不会更新功能了,重点会放在H5播放器上。H5播放器架构主要分四层,底层H5 Video,播放能力和H5原生Video紧密相关。第二层是基础播放器,它不依赖于具体业务,通过URL的方式来播放。第三层是为各种业务场景准备的不同的播放器,可以很容易的扩展,相互隔离不依赖。最上面一层是适配的播放器,会根据终端类型、浏览器类型、播放格式和用户指定来进行智能适配。
播放器功能
最近,我们在播放器端上也实现了截图、国际化、变速、UI自定义、微信同层播放、自适应播放、加密播放、H5播放flv、自定义插件等功能。后续,我们还会通过插件的形式实现弹幕、广告等功能,并会开源到github上,也会支持用户根据自己业务需求来自定义SDK包。
播放器支持视频格式
适配播放
我们整个视频播放的基本原则是H5优先,能用H5播放的肯定不用Flash去播放。所以在移动端,我们肯定是用H5来播放的,PC端也依照这个原则尽量使用H5。同时,我们会判断浏览器类型支持哪种播放格式,比如m3u8在PC端IE11以上的浏览器才能播放,如果遇到IE11以下的浏览器,我们自动会选择Flash播放。在视频格式方面,假设视频是rtmp和flv,我们会自动选择Flash播放。另外,如果用户自主设置useH5Prism和useFlashPrism属性,那我们也会依照用户的选择。
浏览器支持情况
FLASH支持IE8以上,在浏览器上启动允许FLASH运行即可;H5支持IE9以上,m3u8需要在IE11以上才可以运行;其他浏览器都也都是可以支持的。
两种播放方式
source,通过url 去播放
通过点播vid+playauth去播放,第二种方式和视频云结合比较紧密
点播播放格式的选择
点播服务中转码生成的视频格式有很多,包括m3u8、flv、mp4等。播放器有自己的一套逻辑去选择播放格式。对于H5来说,默认播放低清版本来节省流量,如果用户使用了切换清晰度的功能,那我们会默认打开他选择的版本。格式方面,则默认播放mp4,用户也可以设置qualitySort来优先播放高清的的版本。对于Flash来说,默认格式顺序是m3u8、flv、mp4。
创建播放器
引用正确的JS和CSS文件
添加播放器容器 需要设置容器的id属性,另外2.0.1之前的版本要添加prism-player类型。
New Aliplayer创建播放
在线配置,用户可以预先体验下播放器的情况
Aliplayer-Cli创建演示例子
用户需要演示例子的时候,不需要写很多代码,通过这个命令,就可以创建例子,直接体验AliPlayer。
PC端支持m3u8
播放域名启用允许跨域访问
订阅和取消事件
清晰度切换
H5 1.9.9以后的版本和id+playauth播放方式才支持清晰度切换;支持记忆选择的清晰度,当选择的清晰度不能播放时,自动选择下一个清晰度播放。
手动切换视频-H5
这个功能播放器内比较常见。我们把它分成两种情况去处理,如果是地址播放,我们通过loadByUrl来播放;如果是vid+playauth播放,我们通过replayByVidAndPlayAuth的方法来播放。
手动切换视频-flash
地址播放方法与H5的方法一样,vid+playauth播放则需要先销毁播放器,再重新创建播放。
不同地址格式的切换
只能先销毁播放器,再重新选择正确的播放器播放。Github地址看simple demo:https://github.com/alilmq/aliplayer-simple-demo
![b_3_7]
UI自定义
很多用户有这个需求,所以我们的UI是可以隐藏掉的。提供了一个skinLayout的属性,当这个属性没有指定值的时候,UI组件是全部显示。如果是空数组的时候,UI组件全部不显示。并且可以自定义组件的显示和位置,在默认UI基础上去裁剪,2.3.0版本以后,用户也可以通过自定义插件的方式自定义自己的UI。
截屏
H5启用:
FLASH启用:snapshot:true
H5播放器,播放域名需添加允许跨域访问的header
支持订阅snapshoted事件,获取截屏的时间点和数据:
支持设置截图的大小和质量:
支持添加文字水印:
边转变播功能
边转边播是MTS的功能,播放器可以支持这种场景的播放。第一次观看的时候调用MTS API启动转码,边转码边播放,而且可以设置延迟播放。转码中使用直播播放器,转码完成后使用点播方式播放。
H5 android微信同层播放
因为H5在android端微信打开时,会自动全屏播放,覆盖Dom元素。
同层播放一般有两种业务场景,一种是点播的,视频在某个地方播放,下面的评论、播放列表等,demo地址:https://github.com/alilmq/h5demo
还要一种场景是直播场景,视频需要全屏。可以通过设置x5_type:h5启用同层播放。Demo 地址:https://github.com/alilmq/h5livedemo
另外H5微信同层播放,有两篇文章可以参考:
http://player.alicdn.com/aliplayer/docs/blogs/how-to-handle-h5-same-layer.html
http://player.alicdn.com/aliplayer/docs/blogs/how-to-handle-h5-same-layer.html
国际化
提供language属性,用于启用各种语言,默认为zh-cn,可选值为zh-cn or en-us。
倍速播放
提供UI的版本,只提供了0.5、1、1.5、2四种倍速播放;而setspeed方法,可以随意设置倍速播放。这个可能会有一些限制,移动端有的浏览器会不支持,比如android微信。
对于直播播放失败的处理
在播放失败时候,会尝试重新播放,触发onM3u8Retry事件,事件里可以做一些提示,比如主播离开请稍等;如果几次尝试后还是失败,会出发livestreamstop事件,事件里做一些直播失败或结束的提示。
我们也做了一些辅助工具,方便用户去接入和排查问题。
诊断工具
通过错误码描述的映射关系,大概能知道用户的错误所在;
通过vid知道用户播放的是哪个视频;
通过uuid这个唯一标识,可以在日志系统中查到用户的播放状态;
通过requestid和播放时间,可以定位到用户的错误是哪次播放的错误和具体的播放时间。
这里还有一个诊断的功能,可以知道用户环境的具体信息,省去手工获取视频的繁琐,可以快速诊断问题。
地址:http://player.alicdn.com/detection.html
检测工具
关于视频播放失败,我们提供了三种方式,原生H5、阿里云H5、阿里云Flash。我们把播放的日志调出来,通过日志来情况来判断播放失败的原因。举个例子,如果用户刚开始请求数据时就失败的话,那我们会猜测存在鉴权失败的情况;如果加载数据出错,那可能是用户的网络的原因;如果是开始播放后出错,可能就问题就出在解析或播放器不支持等方面。
ffmpeg查看视频信息
有的用户只有画面,没有声音。我们可以通过ffmpeg可以看下视频的格式、流的情况、码率、帧率等。
最后,阿里云播放器的所有情况都聚合在以下的网站上:
http://player.alicdn.com/detection.html,其中包括帮助文档、在线配置、诊断工具、产品demo等,大家可以登录了解详情。
两天有个客户需要把网页转为pdf,之前也没开发过类似的工具,就在百度搜索了一波,主要有下面三种
在百度(我一般用必应)搜索“在线网页转pdf”就有很多可以做这个事的网站,免费的如
各种pdf的操作都有,免费使用,速度一般。
官网地址https://tools.pdf24.org/zh
PDF24 Tools
开源免费项目,使用golang写的,提供在线转
官网地址http://doctron.lampnick.com/
doctron在线体验demo
还有挺多其他的,可以自己搜索,但是都不符合我的预期。
Doctron,这是我今天要介绍的重头戏。
Doctron是基于Docker、无状态、简单、快速、高质量的文档转换服务。目前支持将html转为pdf、图片(使用chrome(Chromium)浏览器内核,保证转换质量)。支持PDF添加水印。
管他的,先把代码下载下来再说
git clone https://gitcode.net/mirrors/lampnick/doctron.git
仓库
运行
go build
./doctron --config conf/default.yaml
运行截图
转pdf,访问http://127.0.0.1:8080/convert/html2pdf?u=doctron&p=lampnick&url=<url>,更换链接中的url为你需要转换的url即可。
转换效果
然后就可以写程序去批量转换需要的网页了,但是我需要转换的网页有两个需求
1、网站需要会员登录,不然只能看得到一部分
2、需要把网站的头和尾去掉的
这就为难我了,不会go语言啊,硬着头皮搞了,肯定有个地方打开这个url的,就去代码慢慢找,慢慢调试,功夫不负有心人,终于找到调用的地方了。
第一步:添加网站用户登录cookie
添加cookie之前
添加cookie之后
第二步:去掉网站头尾
chromedp.Evaluate(`$('.header').css("display" , "none");
$('.btn-group').css("display" , "none");
$('.container .container:first').css("display" , "none");
$('.breadcrumb').css("display" , "none");
$('.footer').css("display" , "none")`, &ins.buf),
打开网页后执行js代码把头尾隐藏掉
第三步:程序化,批量自动生成pdf
public static void createPDF(String folder , String cl , String pdfFile, String urlhref) {
try {
String fileName = pdfFile.replace("/", ":");
String filePath = folder + fileName;
File srcFile = new File(filePath);
File newFolder = new File("/Volumes/disk2/myproject" + File.separator + cl);
File destFile = new File(newFolder, fileName);
if(destFile.exists()){
return;
}
if(srcFile.exists()){
//移动到对应目录
if(!newFolder.exists()){
newFolder.mkdirs();
}
FileUtils.moveFile(srcFile , destFile);
return;
}
if(!newFolder.exists()){
newFolder.mkdirs();
}
String url = "http://127.0.0.1:8888/convert/html2pdf?u=doctron&p=lampnick&url="+urlhref;
HttpEntity<String> entity = new HttpEntity<String>(null, null);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<byte[]> bytes = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class);
if (bytes.getBody().length <= 100) {
if(urlList.containsKey(urlhref)){
Integer failCount = urlList.get(urlhref);
if(failCount > 3){
System.out.println("下载失败:" + cl + " / " + pdfFile +" " + urlhref);
return;
}
failCount++;
urlList.put(urlhref , failCount);
}else{
urlList.put(urlhref , 1);
}
createPDF(folder , cl , pdfFile , urlhref);
}else{
if (!destFile.exists()) {
try {
destFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
try (FileOutputStream out = new FileOutputStream(destFile);) {
out.write(bytes.getBody(), 0, bytes.getBody().length);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
最终成果:
文件夹分类存放
pdf文件
我们的项目开发完成之后通常要做一个演示网站,那么如何防止我们辛苦开发的网站被别人滥用呢?我们可以通过在网页上添加水印来注明所有人的信息,像下面这个样子。
那么如何添加水印呢,今天就来介绍三种比较常用的添加水印的方法。下面所有的网页都以若依的后台管理系统为例。
添加的水印效果如图所示
具体做法是我们定义一个水印的样式——
floating-watermark,然后在需要被添加水印的标签中引用这个样式。样式案例如下:
.floating-watermark {
position: fixed;//这个属性使元素相对于浏览器窗口固定定位,这意味着即使页面滚动,元素也会保持在固定位置 top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
//这个属性设置了元素的背景图像。在这里,使用了一个数据URI来嵌入一个SVG图像。这个SVG图像包含了倾斜的“测试水印”文字
background-image: url('data:image/svg+xml;utf8,<svg xmlns="SVG namespace" width="400" height="400"><text x="50" y="200" font-size="30" fill="rgba(0, 0, 0, 0.1)" transform="rotate(-45, 50, 200)">测试水印</text></svg>');
background-repeat: repeat;
z-index: 1000;//这个属性设置了水印的图层,值越大则越靠上
}
使用Canvas来创建满屏倾斜的水印文字涉及到在Vue组件中使用JavaScript来动态绘制水印。效果如下。
具体做法是在js中定义一个绘制水印的方法——drawWatermark,然后在组件的mounted生命周期钩子中调用drawWatermark方法,以确保在组件加载时绘制并显示水印。样例写法如下。
drawWatermark() {
let canvas = document.createElement('canvas');
const spacing = 300; // 水印间的间距
canvas.width = window.innerWidth * 2; // Canvas的宽度为视口宽度的两倍
canvas.height = window.innerHeight * 2; // Canvas的高度为视口高度的两倍
let ctx = canvas.getContext('2d');
ctx.font = '30px Arial'; // 字体大小
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 字体颜色和透明度
ctx.rotate(-Math.PI / 4); // 将文字旋转45度
// 在Canvas上重复绘制倾斜的文字
for (let x = -canvas.width; x < canvas.width; x += spacing) {
for (let y = -canvas.height; y < canvas.height; y += spacing) {
ctx.fillText('测试水印', x, y);
}
}
// 创建一个新的div元素用于显示水印
const watermarkDiv = document.createElement('div');
watermarkDiv.style.position = 'fixed';
style.top-正在西部数码(www.west.cn)进行交易 = '0';
watermarkDiv.style.left = '0';
watermarkDiv.style.width = '100%';
watermarkDiv.style.height = '100%';
watermarkDiv.style.backgroundImage = `url(${canvas.toDataURL()})`;
watermarkDiv.style.backgroundRepeat = 'repeat';
watermarkDiv.style.pointerEvents = 'none';
watermarkDiv.style.zIndex = '9999'; // 设置高z-index值
document.body.appendChild(watermarkDiv);
}
最后一种方法是利用第三方工具库来实现添加水印的效果,这里我推荐
vue-watermark-directive组件。效果如图所示。
首先我们需要安装vue-watermark-directive组件。
npm install vue-watermark-directive --save
然后在项目中引用组件,修改main.js
import VueWatermark from 'vue-watermark-directive';
最后在标签中使用
<div class="app-container" v-watermark="'测试水印'">
这三种方法中Canvas使用灵活,CSS方法和第三方组件简单易用,大家可以根据自己项目的情况选择一种使用。
更多文章推荐公众号【程序员老J】
*请认真填写需求信息,我们会在24小时内与您取得联系。