视频笔记软件JumpVideo技术解析一:Electron案例-调用VLC播放器
大家好,我是TheGodOfKing,是 最强考研学习神器,免费视频笔记应用JumpVideo,可以快速添加截图时间戳,支持所有笔记软件,学习效率MAX!的开发者之一,分享技术的目的是想找到更多志同道合的人,如果有大学生加入,我们还允许他把项目作为毕设(只有一个名额哟)群(689978959),那么今天要给大家分享软件框架electron一个实用小案例: 调用vlc播放器播放视频并控制vlc播放器,支持生成时间戳、播放、暂停、截图、ab片段播放、ab循环播放、快进、快退等操作
业务说明
还是简单说下需求:electron构建一个app,app主要可以打开本地视频播放,同时app支持设置快捷键来控制打开的播放器.比如使用快捷键截取当前帧并提取相关文字,播放,暂停,等
关于VLC
VLC 媒体播放器(最初为 VideoLAN Client)是一款高度便携的多媒体播放器,可播放各种音频和视频格式(MPEG、DivX/Xvid、Ogg 等)以及 DVD、VCD 和各种流媒体协议。 不过,近年来它也成为了一个功能极其强大的服务器,可将多种格式的实时和点播视频流传输到我们的网络和互联网上。 VLC 由非营利基金会 VideoLAN 制作。
优点
- 支持多种音视频格式
- 跨平台,支持Window、Mac
正因为VLC是跨平台的超强播放器,因此我才会选择VLC作为项目软件的本地视频播放器。
实战:核心代码一:使用系统调用api来打开vlc播放器
关于exec和spawn
exec 和 spawn 是 Node.js 中 child_process 模块提供的两个方法,用于在子进程中执行命令。它们的主要区别在于它们如何处理输入输出数据以及适用的使用场景。
exec
exec 方法用于执行一个 shell 命令并且将其输出(包括标准输出和标准错误)作为一个缓冲区返回。它适用于执行简单的、一次性的命令,并且不需要与子进程进行大量的交互。
使用示例:
const { exec } = require('child_process');
// 执行一个 shell 命令
exec('ls -l', (error, stdout, stderr) => {
if (error) {
console.error(`执行出错: ${error}`);
return;
}
console.log(`标准输出:\n${stdout}`);
console.error(`标准错误:\n${stderr}`);
});
特点:
- 输出作为一个缓冲区(字符串)返回。
- 默认情况下有一个 200KB 的输出限制,可以通过 maxBuffer 选项增加。
- 适用于需要执行简单命令并一次性获取输出的场景。
spawn
spawn 方法用于启动一个新的进程并且为其输入输出流提供一个接口。它更适合处理长时间运行的进程或者需要与子进程进行大量交互的场景。
使用示例:
const { spawn } = require('child_process');
// 启动一个新的进程
const ls = spawn('ls', ['-l']);
ls.stdout.on('data', (data) => {
console.log(`标准输出: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`标准错误: ${data}`);
});
ls.on('close', (code) => {
console.log(`子进程退出码: ${code}`);
});
特点:
- 返回一个 ChildProcess 对象,提供了 stdout 和 stderr 流来实时处理输出。
- 没有输出缓冲区大小限制。
- 适用于需要实时处理输出或者与子进程进行交互的场景。
总结
- 使用 exec 当你需要执行简单命令并获取其输出。
- 使用 spawn 当你需要处理长时间运行的进程,或者需要实时处理进程输出和交互
核心代码二:打开播放器业务代码
async openVLC(videoPath, seekTime = null) {
try {
const isVlcRunning = this.vlcProcess !== null
console.log('vlc.isVlcRunning=', isVlcRunning)
if (isVlcRunning) {
return this.onOpenVideo(videoPath, seekTime)
}
const args = [videoPath]
let selfSeekTime = false
if (seekTime) {
const {
mode,
times
} = this.parseSeekTime(seekTime)
if (mode === 'ab') {
selfSeekTime = true
// A-B片段
args.push(
`--start-time=${times[0]}`,
// `--stop-time=${times[1]}`,
// '--play-and-pause',
)
} else if (mode === 'ab-loop') {
selfSeekTime = true
args.push(
`--start-time=${times[0]}`,
// `--stop-time=${times[1]}`,
// '--loop',
)
} else {
args.push(`--start-time=${this.convertSeekTimeToSeconds(seekTime)}`)
}
}
if (SystemConfig.isWindows) {
args.push('--intf', 'qt')
}
console.log('vlc cmd:', this.vlcPath, args.join(' '))
const vlcProcess = spawn(this.vlcPath, args, {
detached: true,
stdio: 'ignore',
})
vlcProcess.unref()
vlcProcess.on('close', (code) => {
console.log(`VLC process exited with code ${code}`)
this.vlcProcess = null
this.clearAbCheckTimeInterval()
this.clearAbLoopCheckTimeInterval()
})
vlcProcess.on('spawn', () => {
if (selfSeekTime) {
this.seekTimeLoop(seekTime)
}
console.log('VLC opened successfully')
})
this.vlcProcess = vlcProcess
return true
} catch (error) {
console.log(`Failed to open VLC: ${error.message}`)
return false
}
}
代码解释:
- 首先,它检查vlc是否已经在运行,如果是,则调用onOpenVideo方法并返回。
- 然后,根据传入的seekTime参数来处理开始播放的时间。如果seekTime的模式是ab或ab-loop,则会处理A-B片段的播放,并将selfSeekTime设置为true。
- 接下来,根据系统是否是Windows来添加相应的参数。
- 在接下来,使用spawn方法创建一个新的vlc进程,并设置相应的参数和事件监听器。如果selfSeekTime为true,则会调用seekTimeLoop方法。
- 最后,将创建的vlc进程赋值给this.vlcProcess,并返回true表示成功打开vlc。如果出现错误,则会打印错误信息并返回false。
到这里我们就打开了VLC播放器,然后这里在解释下vlc终端指令几个关键参数:
- --start-time 指定开始播放的时间点
- --stop-time 指定结束播放的时间点
- --loop 循环播放
- --intf qt 打开的播放器画面拥有功能栏、进度栏等丰富的界面元素,不加只会弹出一个播放器
基本上,我们现在通过终端指令已经可以实现打开本地任一视频播放了,而且也能实现a-b片段、ab片段循环,当然作者这里实际是放弃了指令实现的ab操作,具体实现有兴趣的朋友可以留言.接下来,我们继续看其他操作的实现.
实现播放、暂停、获取当前播放状态、快进、快退等操作
对于vlc来讲,它已经为我们提供很好的对接方式,那就是vlc http api.因此我们便可以通过接口来实现我们的操作.
第一步:播放器设置http
作者给出mac的设置(默认显示基本,就会有个http 密码设置),️启用并设置vlc密码.就开启了我们http接口.windows用户设置基本一样,具体看vlc软件.
显示基本
显示全部
第二步:查看官方文档
文档地址: VLC HTTP requests - VideoLAN Wiki
第三步: 封装一个请求方法
// 获取 VLC 的当前状态
async getVlcStatus() {
const {
port,
password
} = await this.getVlcConfig()
const url = `http://${SystemConfig.vlcHttpHost}:${port}/requests/status.xml`
try {
const response = await axios.get(url, {
auth: {
username: '',
password: password,
},
})
const parseStringPromise = promisify(xml2js.parseString)
const result = await parseStringPromise(response.data)
return result
} catch (error) {
console.error(`Error fetching VLC status: ${error.message}`)
throw error
}
}
// 发送 VLC HTTP 请求的函数
async sendVlcHttpCommand(command) {
const {
port,
password
} = await this.getVlcConfig()
const url = `http://${SystemConfig.vlcHttpHost}:${port}/requests/status.xml?command=${command}`
console.log('sendVlcHttpCommand:', url)
try {
const response = await axios.get(url, {
auth: {
username: '',
password: password,
},
})
//console.log('vlc http api result:', response.data)
return response.data
} catch (error) {
console.error(`Error sending VLC http command: ${error.message}`)
throw error
}
}
到这里,我们已经实现了electron 操作vlc播放器的大部分需求了. 那最后我们还要在实现一个截取当前播放帧画面.对于它我们来看下该如何实现
实现截图
终端指令和vlc接口都不好使的情况下,我们能想到的是ffmpeg.那这样我们的实现方式就有了: 获取当前播放的视频信息->判断有没有在播的视频->存在信息拿到播放路径和当前播放时间->调用ffmpeg指令
当然,我们这里的场景方案只针对单开的情况,如果vlc开启多开情况(好像可以)就不太对了,不过vlc接口获取的是一个播放列表,说不定可以操作.
async takeScreenshot(videoPath, videoTime, outputDir) {
const outputFilePath = path.join(outputDir, 'vlc-local-video-snapshot.png')
return new Promise((resolve, reject) => {
ffmpeg(decodeURIComponent(videoPath))
.seekInput(videoTime)
.outputOptions('-frames:v 1')
.output(outputFilePath)
.on('end', () => {
console.log(`VlC Local Video Screenshot saved to ${outputFilePath}`)
resolve(outputFilePath)
})
.on('error', (err) => {
console.error(
`VlC Local Video Error taking screenshot: ${err.message}`,
)
reject(err)
})
.run()
})
}
总结
通过以上操作,我们完成了electron调用vlc播放器的需求,如果有大佬对项目感兴趣的可以加群(689978959)私信我,如果是大学生加入我们还允许他把项目作为毕设(只有一个名额哟) ,后续关于如何自己实现ab操作有感兴趣的朋友可以留言。下一期,小编将出一期 electron 调用 potPlayer播放器的文章。
原文
https://juejin.cn/post/7399273700116955186
视频笔记软件JumpVideo技术解析一:Electron案例-调用VLC播放器的更多相关文章
- C# Winform开发程序调用VLC播放器控件播放视频.
VLC是个好东西,支持的格式多,还无广告,关键还有调用它的播放控件不用安装. 开个文章记录下调用这个控件的流水账,以便以后需要的时候查阅 创建工程 首先新建一个Winform工程. 这里姑且叫做VLC ...
- phongap开发中安卓平台上如何调用第三方播放器来播放HLS视频
前文曾经讲了关于在安卓平台上利用phonegap开发播放HLS的解决方案,其实最好的方案就是自己针对HLS视频开发自己的播放器,但是开发播放器是一个浩大的工程,必须对原生安卓开发非常熟悉,并且对视频播 ...
- 使用vlc播放器播放rtsp流视频
可参考: 使用vlc播放器做rtsp服务器 web网页中使用vlc插件播放相机rtsp流视频 使用vlc进行二次开发做自己的播放器 首先需要安装vlc播放器,下载及安装步骤略 使用vlc播放器播放rt ...
- java调用本地播放器播放视频文件。调用本地播放器不能播放指定文件的说明。
public class OpenExe extends HttpServlet { //打开本地播放器并播放视频 public static void openExe(String file) { ...
- xpath技术解析xml以及案例模拟用户登录效果
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!! xpath就在此情况下产生了--主要是用于快速获取所需的[节点对象]. 在dom4j中如何使用xPath技术 1) ...
- 【转】寻找最好的笔记软件:海选篇 (v1.0)
原文网址:http://blog.sina.com.cn/s/blog_46dac66f01000b55.html 序言: 我见过的多数软件爱好者,无论是资深用户,还是初级用户,都有一个梦想:找到 ...
- 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)
前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...
- 百度播放器SDK 播放MP4格式视频有声音无画面问题解决
此处为记录解决过程. 所链接使用的MP4格式视频为codec id是mp4v-20.使用手机自带播放器可以播放,使用百度云媒体播放器不能无画面.经调试,Android Baidu-Cloud-Play ...
- VLC播放RTSP视频延迟问题 (转)
原帖地址:http://blog.chinaunix.net/uid-26611383-id-3755283.html ======================================== ...
- 网页调用vlc并播放网络视频
环境:windows/android/ios windows端保存以下内容为reg文件并运行 Windows Registry Editor Version 5.00 [HKEY_CLASSES_RO ...
随机推荐
- Qt开源作品33-图片开关控件
一.前言 进入智能手机时代以来,各种各样的APP大行其道,手机上面的APP有很多流行的元素,开关按钮个人非常喜欢,手机QQ.360卫士.金山毒霸等,都有很多开关控制一些操作,在WINFORM项目上,如 ...
- 提供Chrome浏览器插件网站
提供Chrome浏览器插件网站: 1.收藏猫插件 2.极简插件
- [转]在MyBatis中使用pageHelper5.1.9分页插件实现物理分页
pagehelper的GIT地址:https://github.com/pagehelper/Mybatis-PageHelper/ 废话少说,直接给出中文官方链接: 1.如何使用分页插件 2.HOW ...
- 关于前端上传excell时间的问题
当前端导入excell里的数据时,只能获取到下面类似的这种数据 Excel存储的日期是从1900年1月1日开始按天数来计算的,也就是说1900年1月1日在Excel中是1. 转化的思路和对Excel中 ...
- 快速上手jquery
优点 强大的选择器机制 优质的隐私迭代 链式编程 选择机制 选择器 标签名 $('div') id $('#id') class $('.clname') 属性 $('div:[name='66']' ...
- 给DevOps加点料:融入安全性的DevSecOps
从前,安全防护只是特定团队的责任,在开发的最后阶段才会介入.当开发周期长达数月.甚至数年时,这样做没什么问题:但是现在,这种做法现在已经行不通了.采用 DevOps 可以有效推进快速频繁的开发周期(有 ...
- 微服务实战系列(七)-网关springcloud gateway-copy
1. 场景描述 springcloud刚推出的时候用的是netflix全家桶,路由用的zuul,但是据说zull1.0在大数据量访问的时候存在较大性能问题,2.0就没集成到springcloud中了, ...
- react 趟坑
最近一直在做react项目,发现一个bug,困扰了我两天. Can't perform a React state update on an unmounted component. This is ...
- Linux 开发环境常用配置
记录下我个人 Linux 开发环境常用配置,后续可以简单写个小脚本可以把一系列安装配置操作自动化一把. zsh install & conf https://blog.csdn.net/amo ...
- linux:权限管理
权限概述 linux一般讲文件可存 / 取 访问的身份分为3个类别:owner.group.others,且3种身份各有 read.write.execute等权限 权限介绍 在多用户计算机系统中,权 ...