在 Go 中利用 ffmpeg 进行视频和音频处理
在 Go 中利用 ffmpeg 进行视频和音频处理
- ffmpegutil 包概述
- 主要功能介绍
- 1. 视频格式转换
- 2. 提取音频
- 3. 获取视频信息
- 4. 创建视频缩略图
- 5. 提取随机帧
- 无线程版本:
- 多线程版本:
- 总结
ffmpeg 是一款功能强大的多媒体处理工具,支持视频和音频的编码、解码、转码,以及帧提取和流处理等功能。它已经成为开发人员处理多媒体内容的首选工具。在本文中,我们将通过一个 Go 封装包 ffmpegutil 来展示如何与 ffmpeg 进行交互,从而简化视频和音频的处理。
我们将介绍一些常见的使用场景,如视频格式转换、音频提取、缩略图创建和帧提取,并探讨如何高效地在 Go 中与 ffmpeg 进行交互。
ffmpegutil 包概述
ffmpegutil 包旨在封装常见的 ffmpeg 操作,为 Go 提供更简洁易用的接口。它包含了以下几个功能:
- 视频格式转换
- 从视频中提取音频
- 获取视频信息和元数据
- 创建视频缩略图
- 在随机时间戳提取帧
该包依赖于 ffmpeg-go 这一 Go 语言的 ffmpeg 封装库,使得 ffmpeg 的功能能够更方便地集成到 Go 项目中。
主要功能介绍
1. 视频格式转换
视频格式转换是 ffmpeg 最常见的应用之一。在 ffmpegutil 中,ConvertVideo 函数通过简单的接口调用,可以将输入的视频文件转换成指定格式。
// ConvertVideo 将视频从一种格式转换为另一种格式
func ConvertVideo(inputFile, outputFile string, key, value string) error {err := ffmpeg.Input(inputFile).Output(outputFile, ffmpeg.KwArgs{key: value}).OverWriteOutput().ErrorToStdOut().Run()if err != nil {return fmt.Errorf("error converting video: %w", err)}log.Debugf("Video conversion complete: %s -> %s", inputFile, outputFile)return nil
}
通过 ffmpeg.Input(inputFile).Output(outputFile, ffmpeg.KwArgs{key: value}),可以设置输入输出文件路径和转换参数。ffmpeg-go 会自动处理转换过程。
2. 提取音频
从视频中提取音频是常见的需求,尤其是在处理视频文件时。ExtractAudio 函数使用 ffmpeg 来实现这一操作。
// ExtractAudio 从视频文件中提取音频
func ExtractAudio(inputFile, outputFile string) error {err := ffmpeg.Input(inputFile).Output(outputFile, ffmpeg.KwArgs{"vn": ""}).Run()if err != nil {return fmt.Errorf("error extracting audio: %w", err)}log.Debugf("Audio extraction complete: %s -> %s", inputFile, outputFile)return nil
}
在 ffmpeg.KwArgs{“vn”: “”} 中,vn 参数表示不处理视频流,仅提取音频流。
3. 获取视频信息
获取视频的基本信息是另一个常见操作。在 ffmpegutil 中,GetVideoInfo 函数通过 ffmpeg.Probe 来获取视频的详细信息。
// GetVideoInfo 获取视频文件的基本信息
func GetVideoInfo(inputFile string) (string, error) {probeData, err := ffmpeg.Probe(inputFile)if err != nil {return "", fmt.Errorf("error getting video info: %w", err)}log.Debugf("Video Info: %v", probeData)return probeData, nil
}
ffmpeg.Probe 返回的视频文件元数据包含格式、时长、码率等信息,可以用于后续的处理。
4. 创建视频缩略图
视频缩略图的生成是视频处理中的常见需求,特别是在多媒体平台上展示视频时。CreateThumbnail 函数从视频中提取一帧作为缩略图。
// CreateThumbnail 为视频创建缩略图
func CreateThumbnail(inputFile, outputFile string) error {err := ffmpeg.Input(inputFile).Output(outputFile, ffmpeg.KwArgs{"vframes": "1", "vf": "scale=800:600"}).Run()if err != nil {return fmt.Errorf("error creating thumbnail: %w", err)}log.Debugf("Thumbnail created: %s -> %s", inputFile, outputFile)return nil
}
该函数通过设置 vframes=1 来提取视频的第一帧,并通过 scale=800:600 来调整缩略图的尺寸。
5. 提取随机帧
提取视频中的随机帧是一个高级操作,通常用于视频分析或生成视频预览图。在 ffmpegutil 中,有两个版本的 ExtractRandomFrames 函数,一个是单线程版本,另一个是多线程版本。
无线程版本:
// ExtractRandomFramesNoThread 提取视频中的随机帧(无线程)
func ExtractRandomFramesNoThread(inputFile, outputDir, filePrefix string, numFrames int) error {// 确保输出目录存在err := os.MkdirAll(outputDir, os.ModePerm)if err != nil {return fmt.Errorf("failed to create output directory: %w", err)}format, err := GetVideoFormat(inputFile)if err != nil {return fmt.Errorf("error getting video format: %w", err)}duration, err := strconv.ParseFloat(format.Format.Duration, 64)if err != nil {return fmt.Errorf("error parsing duration: %w", err)}randSource := rand.NewSource(time.Now().UnixNano())randGen := rand.New(randSource)timestamps := generateRandomTimestamps(duration, numFrames, randGen)for i, timestamp := range timestamps {outputFile := filepath.Join(outputDir, fmt.Sprintf("%s_%03d.jpg", filePrefix, i+1))err := extractFrameAtTimestamp(inputFile, outputFile, timestamp)if err != nil {log.Errorf("Error extracting frame: %v", err)} else {log.Tracef("Frame extracted: %s -> %s", inputFile, outputFile)}}return nil
}
多线程版本:
// ExtractRandomFrames 提取视频中的随机帧(多线程)
func ExtractRandomFrames(inputFile, outputDir, filePrefix string, numFrames, numThreads int) error {// 确保输出目录存在err := os.MkdirAll(outputDir, os.ModePerm)if err != nil {return fmt.Errorf("failed to create output directory: %w", err)}format, err := GetVideoFormat(inputFile)if err != nil {return fmt.Errorf("error getting video format: %w", err)}duration, err := strconv.ParseFloat(format.Format.Duration, 64)if err != nil {return fmt.Errorf("error parsing duration: %w", err)}randSource := rand.NewSource(time.Now().UnixNano())randGen := rand.New(randSource)timestamps := generateRandomTimestamps(duration, numFrames, randGen)var wg sync.WaitGroupsem := make(chan struct{}, numThreads)for i, timestamp := range timestamps {wg.Add(1)go func(index int, ts float64) {defer wg.Done()sem <- struct{}{} // acquire semaphoreoutputFile := filepath.Join(outputDir, fmt.Sprintf("%s_%03d.jpg", filePrefix, index+1))err := extractFrameAtTimestamp(inputFile, outputFile, ts)if err != nil {log.Errorf("Error extracting frame: %v", err)} else {log.Tracef("Frame extracted: %s -> %s", inputFile, outputFile)}<-sem // release semaphore}(i, timestamp)}wg.Wait()return nil
}
总结
通过 ffmpegutil 包,Go 开发者可以轻松实现视频和音频的常见处理任务,如格式转换、音频提取、缩略图生成和随机帧提取。利用 ffmpeg-go 封装库,结合 Go 的并发特性,可以高效地处理大量视频数据,满足复杂的多媒体处理需求。
无论是用于视频分析、音频处理,还是为视频平台生成缩略图,ffmpeg 都是一款必不可少的工具。而通过 Go 对 ffmpeg 的封装,可以更方便地将其集成到自己的项目中,提升开发效率。
相关文章:
在 Go 中利用 ffmpeg 进行视频和音频处理
在 Go 中利用 ffmpeg 进行视频和音频处理 ffmpegutil 包概述主要功能介绍1. 视频格式转换2. 提取音频3. 获取视频信息4. 创建视频缩略图5. 提取随机帧无线程版本:多线程版本: 总结 ffmpeg 是一款功能强大的多媒体处理工具,支持视频和音频的编…...

【机器学习】探索机器学习与人工智能:驱动未来创新的关键技术
探索机器学习与人工智能:驱动未来创新的关键技术 前言:人工智能的核心技术深度学习:自然语言处理(NLP):计算机视觉: 机器学习与人工智能的驱动创新医疗健康领域金融行业智能制造与工业互联网智慧…...
React Refs 完整使用指南
React Refs 完整使用指南 1. Refs 基础用法 1.1 创建和访问 Refs // 类组件中使用 createRef class MyComponent extends React.Component {constructor(props) {super(props);this.myRef React.createRef();}componentDidMount() {// 访问 DOM 节点console.log(this.myRef…...

程控电阻箱应用中需要注意哪些安全事项?
程控电阻箱是一种用于精确控制电路中电流和电压的电子元件,广泛应用于电子实验、测试设备以及精密测量仪器中。在应用程控电阻箱时,为确保安全和设备的正常运行,需要注意以下几个安全事项: 1. 正确连接:确保电阻箱与电…...
C/C++基础知识复习(43)
1) 什么是运算符重载?如何在 C 中进行运算符重载? 运算符重载是指在 C 中为现有的运算符定义新的行为,使得它们能够用于用户定义的数据类型(如类或结构体)。通过运算符重载,可以让自定义类型像内置数据类型…...

苍穹外卖-day05redis 缓存的学习
苍穹外卖-day05 课程内容 Redis入门Redis数据类型Redis常用命令在Java中操作Redis店铺营业状态设置 学习目标 了解Redis的作用和安装过程 掌握Redis常用的数据类型 掌握Redis常用命令的使用 能够使用Spring Data Redis相关API操作Redis 能够开发店铺营业状态功能代码 功能实…...

VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)
名人说:一点浩然气,千里快哉风。—— 苏轼《水调歌头》 创作者:Code_流苏(CSDN) 目录 一、Java开发环境搭建二、VScode下载及安装三、VSCode配置Java环境四、运行测试五、背景图设置 很高兴你打开了这篇博客,更多详细的安装教程&…...
PHP MySQL 插入多条数据
PHP MySQL 插入多条数据 在Web开发中,PHP和MySQL的组合是非常常见的。PHP是一种服务器端脚本语言,而MySQL是一种流行的数据库管理系统。在许多情况下,我们可能需要一次性向MySQL数据库插入多条数据。这可以通过几种不同的方法实现࿰…...

Oracle安装报错:将配置数据上载到资料档案库时出错
环境:联想服务器 windows2022安装Oracle11g 结论:禁用多余网卡先试试,谢谢。 以下是问题描述和处理过程: 网上处理方式: hosts文件添加如下: 关闭防火墙 暂时无法测试通过。 发现ping不是本地状态,而是…...

JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
目录 JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码) 一、为什么要使用Array.sort() 二、Array.sort() 的使用与技巧 1、基础语法 2、返回值 3、…...

Deformable DETR:Deformable Transformers for End-to-End Object Detection论文学习
1. 为什么提出了Deformable DETR? 因为DETR本身的计算量大,收敛速度慢。其次是小目标检测效果差。主要原因是Attention模块每次只关注一小部分采样点,导致需要很多轮数才能学习到真实需要关注的目标。 Deformable DETR注意力模块只关注一个…...

机器学习-43-可解释性机器学习库LIME
文章目录 1 LIME1.1 LIME的特点1.2 LIME的步骤2 应用LIME2.1 分类模型2.1.1 创建模型和解释器2.1.2 解释样本2.2 回归模型2.2.1 创建模型和解释器2.2.2 解释样本2.3 文本模型2.3.1 创建模型和解释器2.3.2 解释样本2.4 图像模型2.4.1 创建模型和解释器2.4.2 解释样本3 附录3.1 l…...

【Unity功能集】TextureShop纹理工坊(五)选区
项目源码:在终章发布 索引 选区PS选区选区功能点提炼 TextureShop选区方形区域中间镂空边框的流动虚线SelectedRegion类选择选区更新选区 选区 选区,也既是在当前选中图层中,已选择的编辑区域,我们后续的所有图像编辑操作&#x…...
Spring Cloud OpenFeign快速入门demo
一、应用场景 Spring Cloud OpenFeign 是一个声明式的 HTTP 客户端,旨在简化微服务之间的通信。它使得开发者能够通过简单的接口定义和注解来调用 RESTful API,极大地减少了样板代码。以下是一些典型的应用场景: 微服务间调用:在…...

研发效能DevOps: Vite 使用 Element Plus
目录 一、实验 1.环境 2.初始化前端项目 3.安装 vue-route 4.安装 pinia 5.安装 axios 6.安装 Element Plus 7.gitee创建工程 8. 配置路由映射 9.Vite 使用 Element Plus 二、问题 1.README.md 文档推送到gitee未自动换行 2.访问login页面显示空白 3.表单输入账户…...

sfnt-pingpong -测试网络性能和延迟的工具
sfnt-pingpong 是一个用于测试网络性能和延迟的工具,通常用于测量不同网络环境下的数据包传输性能、吞吐量、延迟等指标。 它通常是基于某种网络协议(如 TCP)执行“ping-pong”式的测试,即客户端和服务器之间相互发送数据包&…...
Kubernetes、Docker 和 Docker Registry 关系是是什么?
Kubernetes(常简称为 k8s)、Docker 和 Docker Registry 是现代云原生应用中三个关键的组件,它们各自承担不同的职责,但在容器化部署和管理过程中紧密协作。以下是它们之间关系的详细解释: 一、核心概念简介 1. Docker…...
docker部署微信小程序自动构建发布和更新
通过 Jenkins 和 Docker 部署微信小程序,并实现自动构建、发布和版本更新,主要涉及以下几个步骤: 设置 Jenkins 环境配置 GitLab 与 Jenkins 的集成构建 Docker 镜像部署和发布微信小程序配置 Jenkins 自动构建 以下是详细的步骤说明&#…...
模仿elementui的Table,实现思路
vue2子组件使用render,给子子组件插槽传值 和elementui的Table一样使用render 在 Vue 2 中,子组件使用render函数向子子组件插槽传值可以通过以下步骤实现: 1、创建子组件 首先创建一个子组件,在子组件中使用render函数来渲染内容…...

Unity中使用环形缓冲区平滑抖动值
环形缓冲数据结构,就是如下图一样的一个收尾相接的列表 在index指针指到4时,再往里添加数据,index就会指向0,并覆盖已有数据。 如何绘制Sin函数,请看下面一篇文章 Unity中如何实现绘制Sin函数图像-CSDN博客 接下来要…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...