大家好,我是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播放器的更多相关文章

  1. C# Winform开发程序调用VLC播放器控件播放视频.

    VLC是个好东西,支持的格式多,还无广告,关键还有调用它的播放控件不用安装. 开个文章记录下调用这个控件的流水账,以便以后需要的时候查阅 创建工程 首先新建一个Winform工程. 这里姑且叫做VLC ...

  2. phongap开发中安卓平台上如何调用第三方播放器来播放HLS视频

    前文曾经讲了关于在安卓平台上利用phonegap开发播放HLS的解决方案,其实最好的方案就是自己针对HLS视频开发自己的播放器,但是开发播放器是一个浩大的工程,必须对原生安卓开发非常熟悉,并且对视频播 ...

  3. 使用vlc播放器播放rtsp流视频

    可参考: 使用vlc播放器做rtsp服务器 web网页中使用vlc插件播放相机rtsp流视频 使用vlc进行二次开发做自己的播放器 首先需要安装vlc播放器,下载及安装步骤略 使用vlc播放器播放rt ...

  4. java调用本地播放器播放视频文件。调用本地播放器不能播放指定文件的说明。

    public class OpenExe extends HttpServlet { //打开本地播放器并播放视频 public static void openExe(String file) { ...

  5. xpath技术解析xml以及案例模拟用户登录效果

    问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!! xpath就在此情况下产生了--主要是用于快速获取所需的[节点对象]. 在dom4j中如何使用xPath技术 1) ...

  6. 【转】寻找最好的笔记软件:海选篇 (v1.0)

    原文网址:http://blog.sina.com.cn/s/blog_46dac66f01000b55.html   序言: 我见过的多数软件爱好者,无论是资深用户,还是初级用户,都有一个梦想:找到 ...

  7. 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)

    前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...

  8. 百度播放器SDK 播放MP4格式视频有声音无画面问题解决

    此处为记录解决过程. 所链接使用的MP4格式视频为codec id是mp4v-20.使用手机自带播放器可以播放,使用百度云媒体播放器不能无画面.经调试,Android Baidu-Cloud-Play ...

  9. VLC播放RTSP视频延迟问题 (转)

    原帖地址:http://blog.chinaunix.net/uid-26611383-id-3755283.html ======================================== ...

  10. 网页调用vlc并播放网络视频

    环境:windows/android/ios windows端保存以下内容为reg文件并运行 Windows Registry Editor Version 5.00 [HKEY_CLASSES_RO ...

随机推荐

  1. 关于TB交易开拓者的KDJ指标与经典KDJ指标计算方法不同的分析

    我之前在群里咨询的问题, TB官方的技术大佬,给出详细的分析 原链接:https://www.kdocs.cn/l/cgF3sA7ypa99 在这,我只复制最核心的内容,如果需要深入研究, 请联系我, ...

  2. 超轻巧modbus调试助手使用说明

    一.使用说明 1.1 数据格式 和其他的modbus采集工具一样,本组件也支持各种数据格式,其实就是高字节低字节的顺序. 一般是2字节表示一个数据,后面又有4字节表示一个数据,目前好像还有8字节表示一 ...

  3. Qt编写地图综合应用55-海量点位标注

    一.前言 海量点位标注的出现,是为了解决普通设备点超过几百个性能极速降低的问题,普通的marker标注由于采用的是对象的形式存在于地图中,数量越多,占用内存特别大,超过1000个点性能极其糟糕,哪怕是 ...

  4. Qt音视频开发6-ffmpeg解码处理

    一.前言 采用ffmpeg解码,是所有视频监控开发人员必备的技能,绕不过去的一个玩意,甚至可以说是所有音视频开发人员的必备技能.FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开 ...

  5. AOP-Redis缓存

    我没有单独使用过Redis,细节我可能解释不到位.该文章是采用依赖注入实现AOP-Redis缓存功能的 . 之前有写实现Memory缓存的.异曲同工之妙. 使用Redis离不开安装get包:Stack ...

  6. Error: Assertion failed (nimages > 0) in cv::calibrateCameraRO, file D:\opencv4\opencv\opencv-4.1.0\modules\calib3d\src\calibration.cpp, line 3691

    报错信息: Error: Assertion failed (nimages > 0) in cv::calibrateCameraRO, file D:\opencv4\opencv\open ...

  7. _findnext()调试中断,发生访问错误,错误定位到ntdll.dll

    问题: 采用_findfirst和_findnext获取指定的文件夹下的文件时,_findnext()函数在调试时发生中断,发生访问错误,错误定位到ntdll.dll.错误提示如下所示: _findn ...

  8. CentOS安装tigerVNC Server

  9. Docker Inspect 模板

    Docker 使用Go 模板,您可以使用它来操作某些命令和日志驱动程序的输出格式. Docker 提供了一组基本函数来操作模板元素.所有这些示例都使用该docker inspect命令,但许多其他 C ...

  10. SpringBoot(六) - 阿里巴巴的EasyExcel

    1.依赖 <!-- 阿里EasyExcel start --> <dependency> <groupId>com.alibaba</groupId> ...