194 lines
7.3 KiB
JavaScript
194 lines
7.3 KiB
JavaScript
|
/**
|
||
|
* 当主页中的“选择视频”按钮被点击后, 执行此函数
|
||
|
*
|
||
|
* 1) 弹出一个文件选择框, 让用户选定一些本地文件
|
||
|
*/
|
||
|
function onSelectVideoButtonClicked() {
|
||
|
// 当用户选定了一些文件后, 函数 onUploadVideoChanged 将被执行.
|
||
|
$('#upload-video').click();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 当主页中的“选择视频”按钮被点击后, 且用户选定了一些文件时, 此函数将被调用.
|
||
|
*
|
||
|
* 1) 检查这些文件的格式. 目前可以处理的视频文件格式是*.mp4
|
||
|
* 2) 将按钮'select-video'隐藏
|
||
|
* 3) 将表格'status-table'显示
|
||
|
*
|
||
|
* 对于每个已选定的文件, 均执行以下异步流程:
|
||
|
*
|
||
|
* 1) 调用服务器的接口, 将文件上传到服务器
|
||
|
* 2) 将标题'caption'修改为 '正在处理{files.length}个文件, 请稍候查看结果'
|
||
|
* 3) 为表格'status-table'追加一行, 用于展示处理当前文件的状态与进度, 并提供用户可执行的操作
|
||
|
*
|
||
|
* @param {file} files 用户选择的文件列表.
|
||
|
*/
|
||
|
function onUploadVideoChanged(files) {
|
||
|
for (var index = 0; index < files.length; index++) {
|
||
|
var file = files[index];
|
||
|
console.log(index);
|
||
|
if (file.type != 'video/mp4') {
|
||
|
errorModal('错误', `文件${file.name}的格式错误`);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
$('#select-video').hide();
|
||
|
$('#status-table').show();
|
||
|
$('#caption').html('正在处理' + files.length + '个文件');
|
||
|
$.each(files, function(index, file) {
|
||
|
uploadFile(index, file);
|
||
|
appendRowToStatusTable(index, file);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 当文件完成部分上传时, 此函数将被回调, 用于更新部分页面组件.
|
||
|
*
|
||
|
* 1) 将表格 status-table 中进度栏的进度信息修改为 '${percent}%'
|
||
|
*
|
||
|
* @param {index} index 文件的索引
|
||
|
* @param {number} percent 文件的上传进度
|
||
|
*/
|
||
|
function onFileUploadStepped(index, percent) {
|
||
|
prog = $(`#stat-prog-${index}`);
|
||
|
prog.css({'width': `${percent}%`});
|
||
|
prog.html(`${percent}%`);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 当文件上传成功后, 此函数将被回调, 用于开始进行特征提取, 同时更新部分界面组件.
|
||
|
*
|
||
|
* 1) 将表格 status-table 中状态栏的信息改为 '正在提取'
|
||
|
* 2) 将表格 status-table 中进度栏的进度信息重置为 '0%'
|
||
|
* 3) 调用服务器接口, 开始执行推理
|
||
|
*
|
||
|
* @param {number} index 文件的索引
|
||
|
* @param {File} file 文件对象
|
||
|
* @param {object} data 服务器响应数据
|
||
|
*/
|
||
|
function onFileUploadFinished(index, file, data) {
|
||
|
$(`#stat-label-${index}`).html('正在提取');
|
||
|
$(`#stat-prog-${index}`).css({'width': '0%'});
|
||
|
$(`#stat-prog-${index}`).html('0%');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 当文件上传失败后, 此函数将被回调, 用于更新部分界面组件.
|
||
|
*
|
||
|
* 1) 将表格 status-table 中的状态栏信息改为 '上传失败'.
|
||
|
* 2) 将表格 status-table 中进度栏的进度信息重置为 '0%'
|
||
|
* 3) 将表格 status-table 中操作栏的按钮修改为 danger, 并激活以查看失败原因.
|
||
|
*
|
||
|
* @param {number} index 文件的索引
|
||
|
* @param {File} file 文件对象
|
||
|
* @param {error} err 失败原因
|
||
|
*/
|
||
|
function onFileUploadFailed(index, file, err) {
|
||
|
$(`#stat-label-${index}`).html('<div class="text-danger">上传失败</div>');
|
||
|
$(`#stat-prog-${index}`).css({'width': '0%'});
|
||
|
$(`#stat-prog-${index}`).html('0%');
|
||
|
$(`#stat-button-${index}`).removeClass('btn-dark disabled');
|
||
|
$(`#stat-button-${index}`).addClass('btn-danger');
|
||
|
$(`#stat-button-${index}`).find('span').remove();
|
||
|
$(`#stat-button-${index}`).text('查看');
|
||
|
$(`#stat-button-${index}`).on('click', function() {
|
||
|
errorModal('错误', `文件${file.name}上传失败: ${err}`);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 上传指定的文件到服务器的接口.
|
||
|
*
|
||
|
* 此函数会回调 onFileUploadStepped 函数, 告知文件的上传进度.
|
||
|
*
|
||
|
* @param {index} index 文件的索引
|
||
|
* @param {file} file 文件对象
|
||
|
*/
|
||
|
function uploadFile(index, file) {
|
||
|
var formData = new FormData();
|
||
|
formData.append('file', file);
|
||
|
$.ajax({
|
||
|
url: 'http://127.0.0.1:8000/upload',
|
||
|
type: 'POST',
|
||
|
data: formData,
|
||
|
processData: false, // 不处理发送的数据
|
||
|
contentType: false, // 不设置内容类型
|
||
|
success: function(data) {
|
||
|
onFileUploadFinished(index, file, data);
|
||
|
},
|
||
|
error: function(xhr, status, error) {
|
||
|
if (xhr.status == 0) {
|
||
|
error = '连接到服务器失败!';
|
||
|
} else {
|
||
|
var errorAjax = `AJAX error: ${status} : ${error}`;
|
||
|
var errorResponseText = `ResponseText: ${xhr.responseText}`;
|
||
|
var errorStatusText = `StatusText: ${xhr.statusText}`;
|
||
|
error = `${errorAjax} + \n\n + ${errorResponseText} + \n\n + ${errorStatusText}`;
|
||
|
}
|
||
|
onFileUploadFailed(index, file, error);
|
||
|
},
|
||
|
xhr: function() {
|
||
|
var xhr = new window.XMLHttpRequest();
|
||
|
xhr.upload.addEventListener('progress', function(event) {
|
||
|
if (event.lengthComputable) {
|
||
|
var percent = event.loaded / event.total;
|
||
|
percent = parseInt(percent * 100);
|
||
|
onFileUploadStepped(index, percent);
|
||
|
}
|
||
|
}, false);
|
||
|
return xhr;
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 在结果窗口中播放服务器中编号为id的视频.
|
||
|
*
|
||
|
* @param {string} id 服务器视频id
|
||
|
*/
|
||
|
function playFile(index, file, id) {
|
||
|
$('#video-modal').find('.modal-title').text(`预览${file ? file.name : '此视频'}的关键镜头`);
|
||
|
$('#video-modal').find('video').attr('src', `http://127.0.0.1:8000/fetch/${id}`);
|
||
|
var player = new Plyr('video');
|
||
|
$('#video-modal').modal();
|
||
|
$('#video-modal').on('hidden.bs.modal', function(event) {
|
||
|
player.pause();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 向表格'status-table'中增加一行, 向用户展示上传文件的信息与当前状态, 并提供必要的操作.
|
||
|
*
|
||
|
* @param {number} index 正在处理的文件编号.
|
||
|
* @param {file} file 正在处理的文件对象.
|
||
|
* @note 在执行此函数时, 该文件对象可能正在异步上传.
|
||
|
*/
|
||
|
function appendRowToStatusTable(index, file) {
|
||
|
var fileNameHtml = `<td>${file.name}</td>`;
|
||
|
var fileTypeHtml = `<td>${file.type}</td>`;
|
||
|
var fileSizeHtml = `<td>${getReadableSize(file.size)}</td>`;
|
||
|
var fileStatHtml = `<td id='stat-label-${index}'>正在上传</td>`;
|
||
|
var fileProgHtml = `<td><div class='progress'><div id='stat-prog-${index}' class='progress-bar' style='width:0%'>0%</div></div></td>`;
|
||
|
var fileOptrHtml = `<td><button id='stat-button-${index}' type='button' class='btn btn-dark btn-sm disabled'><span class="spinner-border spinner-border-sm"></span></button></td>`;
|
||
|
$('#status-table').append(
|
||
|
'<tr>' + fileNameHtml + fileTypeHtml + fileSizeHtml + fileStatHtml + fileProgHtml + fileOptrHtml + '</tr>'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// 注册按钮点击事件处理函数
|
||
|
$(document).ready(function() {
|
||
|
$('#select-video').click(onSelectVideoButtonClicked);
|
||
|
});
|
||
|
|
||
|
// 注册文件选择事件处理函数
|
||
|
$(document).ready(function() {
|
||
|
$('#upload-video').change(function() {
|
||
|
var files = $(this).prop('files');
|
||
|
onUploadVideoChanged(files);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
$(document).ready(function() {
|
||
|
playFile(0, null, '123');
|
||
|
});
|