今天准备整理一篇关于《video使用HTML5的canvas画布功能实现视频在线截图功能,并把相关图片上传服务器》
·思路分析:
1. 使用canvas画布功能画出当前video实时界面,并将画布图片转为base64数据;
2. 通过ajax传到后端,再做图片生成并上传服务器对应位置;
3. 把相关数据存储记录表并反馈处理结果。
·效果展示:
将画布产生的base64数据在img中展示查看截图效果:
·canvas画布资源获取:
<video crossOrigin="anonymous" id="my_video_1" style="width: 300px;height: 480px;" preload="metadata" autoplay="autoplay" class="video-js vjs-fluid"></video>
JS数据处理:
// 截图当前视频画面,预览后传递后端进行服务器保存
var base64Url= ""; //定义为全局变量
function screenshotsVideo() {
base64Url = getScreenshotsVideoImg();
var imgObj=document.getElementById("screenshotsVideoImg");
//生成img展示
imgObj.src=base64Url;
}
// 构造canvas 生成图片base64数据
function getScreenshotsVideoImg() {
var _videoWidth = 0;
var _videoHeight = 0;
var _canvas ;
var _ctx ;
var _video;
_canvas = document.createElement('canvas');
_ctx = _canvas.getContext("2d");
_video = document.querySelectorAll('video')[0];
_videoWidth = _video.videoWidth ;//视频原有尺寸
_videoHeight = _video.videoHeight;//视频原有尺寸
_canvas.width =_videoWidth;
_canvas.height =_videoHeight;
_ctx.drawImage(_video, 0, 0,_videoWidth,_videoHeight);
var base64 = _canvas.toDataURL('image/jpeg');
console.log("toDataURL save complete!");
return base64;
}
点击按钮,触发数据传送:
// 将截图base64资源,传递后端处理
function saveScreenshots(){
myModalData = "";
if (null != contentData) {
var photoDescribeText = $('#photoDescribeText').val();
if(null == photoDescribeText || '' == photoDescribeText){
toastr.info('请填写截图问题描述!');
return;
}
$.ajax({
type : "post", //请求类型
url : "../../../****.json",//请求的 URL地址
data:{
base64Url : base64Url,
videoPlayUrl : videoPlayUrl.substring(0,videoPlayUrl.length-1),
auditType : '1', //审核类型 1:复审
photoDescribe:photoDescribeText,
contentCode : contentData.contentCode,
contentName : contentData.contentName,
},
dataType : "json",//返回的数据类型
success: function (data) {
console.log("data"+data);
if(data.success){
$('#photoDescribeText').val(""); //清空图片问题描述
$("#screenshotsVideoModal").modal('hide'); //关闭模态框
toastr.success('截图保存成功!');
}else{
toastr.error('截图保存失败!');
}
},
error:function (data) {
console.log("data"+data);
toastr.error('截图保存失败!');
}
});
}
}
·后端图片上传和数据保存处理:
//保存视频截图接口
public String mgdmSaveVideoScreenshots() {
try {
getParams();
String base64Url = this.getParam("base64Url");
base64Url = base64Url.split(",")[1];
String photoAddress = handlePicAdds(base64Url); // 获取本地存储图片相对地址
if (StringUtil.isNullStr(photoAddress)){
//如果图片没有上传成功,直接返回错误结束方法
resultMap.put("success", false);
resultMap.put("resultMessage",this.getText("operateFailed"));
return SUCCESS;
}
params.put("photoAddress", photoAddress);
params.put("operId", this.getUserId());
params.put("operator", this.getUsername() + "_YSSHY");
Boolean saveResult = auditPhotoScreenshotManager.saveAuditPhotoScreenshot(params);
if(saveResult){
resultMap.put("success", true);
resultMap.put("resultMessage",this.getText("operateSuccess"));
}else{
resultMap.put("success", false);
resultMap.put("resultMessage",this.getText("operateFailed"));
}
} catch (Exception e) {
e.printStackTrace();
resultMap.put("success", false);
resultMap.put("resultMessage",this.getText("operateFailed"));
}
return SUCCESS;
}
public String handlePicAdds(String base64Url){
String localPicAdds = params.get("contentCode")+"-"+DateUtil.formatDate(DateUtil.DATE_TIME_HHMMSS,new Date());
String todayPath = nowDatePath();
String localPicName = todayPath+localPicAdds+CmsConstants.PIC_JPG;
Boolean downLoad = writeFileToLocal(base64Url,localPicAdds); //将图片上传到服务器
String localPicAdd = "";
if(downLoad){
localPicAdd = localPicName;
}
return localPicAdd;
}
//将图片下载到本地
public Boolean writeFileToLocal(String base64Url,String localPath){
try {
BASE64Decoder decoder = new BASE64Decoder();
// Base64解码
byte[] buffer = decoder.decodeBuffer(base64Url);
for (int i = 0; i < buffer.length; ++i) {
if (buffer[i] < 0) {// 调整异常数据
buffer[i] += 256;
}
}
String todayPath = nowDatePath();
String serverPicPath = SyncConstants.POMS_MGDM_SERVER_PIC_PATH+todayPath; //服务器图片存储文件路径
File file = new File(serverPicPath);
if(!file .exists()){
file.mkdirs();
}
FileOutputStream fileOutputStream = new FileOutputStream(new File(serverPicPath+localPath+CmsConstants.PIC_JPG));
fileOutputStream.write(buffer);
fileOutputStream.close();
return true;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
public String nowDatePath(){
//根据日期创建 图片存储路径
Calendar calendar = Calendar.getInstance();
Integer year = calendar.get(Calendar.YEAR);
Integer month = calendar.get(Calendar.MONTH) + 1;
Integer date = calendar.get(Calendar.DAY_OF_MONTH);
String pathStr = CmsConstants.PATH_SEPARATOR;
String severPath = pathStr+year+pathStr+month+pathStr+date+pathStr;
return severPath;
}
·注意问题:
1.在处理的过程中,遇到video视频资源跨域导致canvas画布污染的问题,处理的时候可以参考下面:
https://www.jianshu.com/p/6fe06667b748
很长一段时间没有记录博客了,上半年因为换工作和准备软考的事情一度停更了半年,接下来希望能在这里将工作和学习中好的知识点总结下来,以供自己和朋友们参考。