FFmpeg+javacpp+javacv使用

news2024/10/6 16:29:18

FFmpeg+javacpp+javacv使用

  • Bytedeco官网案例
  • 1、导入opencv、ffmpeg依赖包
  • 2、FFmpeg 数据结构
    • 2.1 AVFormatContext 格式化I/O上下文
      • 2.1.1 metadata
      • 2.1.2 Duration、start、bitrate等其他信息
      • 2.1.3 dump信息

Bytedeco
GitHub:javacpp

Bytedeco官网案例

FFmpeg – [示例用法] [API] – 一个完整的跨平台解决方案,用于录制、转换和流式传输音频和视频
FFmpeg 6.1.1 http://ffmpeg.org/ 关于 FFmpeg
JavaCPP Presets for FFmpeg 6.1.1-1.5.10 API
javacv:https://github.com/bytedeco/javacv


坑哧吭坑: 这可能是最详细的javaCV-FFmpeg防踩坑入门了
javaCV入门指南
雷霄骅(leixiaohua1020)的专栏 FFmpeg
FFmpeg - 打造一款万能的音乐播放器

1、导入opencv、ffmpeg依赖包

ext {
    javacvVersion = '1.5.9'
    ffmpegVersion = '6.0'
    windowsVersion = 'windows-x86_64'
}

dependencies {
    /* javacv + FFmpeg */
    // implementation group: 'org.bytedeco', name: 'javacv-platform', version: "$javacvVersion"
    implementation "org.bytedeco:javacpp:${javacvVersion}:${windowsVersion}"
    implementation "org.bytedeco:javacv:${javacvVersion}"
    implementation "org.bytedeco:ffmpeg:${ffmpegVersion}-${javacvVersion}"
    implementation "org.bytedeco:ffmpeg:${ffmpegVersion}-${javacvVersion}:${windowsVersion}"

    testImplementation platform('org.junit:junit-bom:5.9.1')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}

在这里插入图片描述

2、FFmpeg 数据结构

2.1 AVFormatContext 格式化I/O上下文

在这里插入图片描述

这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。其中nb_streamsstreams所表示的AVStream结构指针数组包含了所有内嵌媒体流的描述;iformatoformat指向对应的demuxer和muxer指针;pb则指向一个控制底层数据读写的ByteIOContext结构。 start_timeduration是从streams数组的各个AVStream中推断出的多媒体文件的起始时间和长度,以微妙为单位。 通常,这个结构由av_open_input_file在内部创建并以缺省值初始化部分成员。但是,如果调用者希望自己创建该结构,则需要显式为该结构的一些成员置缺省值;如果没有缺省值的话,会导致之后的动作产生异常。

String url = "C:\\Users\\Administrator\\Desktop\\Let Me Down Slowly.mp3";
// 解封装上下文
AVFormatContext pFormatCtx = new AVFormatContext(null);
if (null == pFormatCtx) {
    XLog.e("获取解封装上下文失败");
    return;
}

// 打开流媒体
if (avformat_open_input(pFormatCtx, url, null, null) != 0) {
    XLog.e("打开媒体失败");
    return;
}

// 读取流媒体数据,以获得流的信息
if (avformat_find_stream_info(pFormatCtx, (PointerPointer<Pointer>) null) < 0) {
    XLog.e("获得媒体流信息失败");
    return;
}

2.1.1 metadata

在这里插入图片描述

AVDictionaryEntry tag = null;
tag = av_dict_get(pFormatCtx.metadata(), "", tag, AV_DICT_IGNORE_SUFFIX);
while (tag != null) {
    XLog.d("tag.key : " + tag.key().getString() + "; tag.value : " + tag.value().getString());
    tag = av_dict_get(pFormatCtx.metadata(), "", tag, AV_DICT_IGNORE_SUFFIX);
}

在这里插入图片描述

2.1.2 Duration、start、bitrate等其他信息

时间基准 public static final int AV_TIME_BASE = 1000000;
在这里插入图片描述

XLog.d("pFormatCtx url() = " + pFormatCtx.url().getString());
XLog.d("pFormatCtx start_time() = " + pFormatCtx.start_time());
XLog.d("pFormatCtx duration() = " + pFormatCtx.duration());
XLog.d("pFormatCtx bit_rate() = " + pFormatCtx.bit_rate());

在这里插入图片描述

2.1.3 dump信息

av_dump_format(pFormatCtx, 0, url, 0);
在这里插入图片描述

源码ffmpeg-6.0\libavformat\dump.c

void av_dump_format(AVFormatContext *ic, int index,
                    const char *url, int is_output)
{
    int i;
    uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL;
    if (ic->nb_streams && !printed)
        return;

    av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n",
           is_output ? "Output" : "Input",
           index,
           is_output ? ic->oformat->name : ic->iformat->name,
           is_output ? "to" : "from", url);
    dump_metadata(NULL, ic->metadata, "  ");

    if (!is_output) {
        av_log(NULL, AV_LOG_INFO, "  Duration: ");
        if (ic->duration != AV_NOPTS_VALUE) {
            int64_t hours, mins, secs, us;
            int64_t duration = ic->duration + (ic->duration <= INT64_MAX - 5000 ? 5000 : 0);
            secs  = duration / AV_TIME_BASE;
            us    = duration % AV_TIME_BASE;
            mins  = secs / 60;
            secs %= 60;
            hours = mins / 60;
            mins %= 60;
            av_log(NULL, AV_LOG_INFO, "%02"PRId64":%02"PRId64":%02"PRId64".%02"PRId64"", hours, mins, secs,
                   (100 * us) / AV_TIME_BASE);
        } else {
            av_log(NULL, AV_LOG_INFO, "N/A");
        }
        if (ic->start_time != AV_NOPTS_VALUE) {
            int secs, us;
            av_log(NULL, AV_LOG_INFO, ", start: ");
            secs = llabs(ic->start_time / AV_TIME_BASE);
            us   = llabs(ic->start_time % AV_TIME_BASE);
            av_log(NULL, AV_LOG_INFO, "%s%d.%06d",
                   ic->start_time >= 0 ? "" : "-",
                   secs,
                   (int) av_rescale(us, 1000000, AV_TIME_BASE));
        }
        av_log(NULL, AV_LOG_INFO, ", bitrate: ");
        if (ic->bit_rate)
            av_log(NULL, AV_LOG_INFO, "%"PRId64" kb/s", ic->bit_rate / 1000);
        else
            av_log(NULL, AV_LOG_INFO, "N/A");
        av_log(NULL, AV_LOG_INFO, "\n");
    }

    if (ic->nb_chapters)
        av_log(NULL, AV_LOG_INFO, "  Chapters:\n");
    for (i = 0; i < ic->nb_chapters; i++) {
        const AVChapter *ch = ic->chapters[i];
        av_log(NULL, AV_LOG_INFO, "    Chapter #%d:%d: ", index, i);
        av_log(NULL, AV_LOG_INFO,
               "start %f, ", ch->start * av_q2d(ch->time_base));
        av_log(NULL, AV_LOG_INFO,
               "end %f\n", ch->end * av_q2d(ch->time_base));

        dump_metadata(NULL, ch->metadata, "      ");
    }

    if (ic->nb_programs) {
        int j, k, total = 0;
        for (j = 0; j < ic->nb_programs; j++) {
            const AVProgram *program = ic->programs[j];
            const AVDictionaryEntry *name = av_dict_get(program->metadata,
                                                        "name", NULL, 0);
            av_log(NULL, AV_LOG_INFO, "  Program %d %s\n", program->id,
                   name ? name->value : "");
            dump_metadata(NULL, program->metadata, "    ");
            for (k = 0; k < program->nb_stream_indexes; k++) {
                dump_stream_format(ic, program->stream_index[k],
                                   index, is_output);
                printed[program->stream_index[k]] = 1;
            }
            total += program->nb_stream_indexes;
        }
        if (total < ic->nb_streams)
            av_log(NULL, AV_LOG_INFO, "  No Program\n");
    }

    for (i = 0; i < ic->nb_streams; i++)
        if (!printed[i])
            dump_stream_format(ic, i, index, is_output);

    av_free(printed);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1861491.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言·动态内存管理

1. 为什么要有动态内存管理&#xff1f; 例1&#xff1a; //固定的向内存申请4个字节 int a 10;//申请连续的一块空间 int arr[10]; 这些数据一旦声明定义之后就会在内存中有一块空间&#xff0c;这些空间都是固定的&#xff0c;为了让内存使用更加灵活&#xff0c;这时我们…

【回溯算法题记录】组合总和题汇总

组合总和 39. 组合总和题目描述初始思路后续分析 40. 组合总和 II题目描述思路&#xff08;参考代码随想录&#xff09; 39. 组合总和 题目&#x1f517; 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数…

开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时&#xff0c;也带来了对安全风险防范能力的挑战。基于此&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;&#xff0c;联合开源…

教你使用 Go 语言访问智谱 AI 大模型!

AI 大模型太火爆了&#xff01;我在工作中经常使用它们&#xff0c;感觉已经离不开了&#xff01; 最近测试了智谱 AI 大模型&#xff0c;实测下来感觉还挺不错的。 官方提供了体验包&#xff0c;注册并实名认证之后有 300 万 token&#xff0c;非常壕&#xff01; 今天的股…

uni-push(2.0)常见问题,Android平台

将常用的网址一定要收藏在标签栏中&#xff0c;方便后期找&#xff0c;不然后期会很生气。 草料二维码&#xff0c;这个在线工具可以将打包生成的apk文件生成二维码&#xff0c;供测试人员测试。生成的apk只有五次下载机会&#xff0c;可点击链接后的一键上传&#xff0c;这样…

站在巨人的肩膀上 C语言理解和简单练习(包含指针前的简单内容)

1.格式化的输入/输出 1.1printf函数 printf函数你需要了解的就是转换说明&#xff0c;转换说明的作用是将内存中的二进制转换成你所需要的格式入%d就是将内存中存储的变量的二进制转化为十进制并打印出来&#xff0c;同时我们可以在%X的转换说明对精度和最小字段宽度的指定&a…

如何在SpringBoot中自定义starter

如何在SpringBoot中自定义starter Spring Boot 提供了一种简便的方法来创建自定义的 starter&#xff0c;从而帮助开发者封装常用的配置和依赖。本文将介绍如何在 Spring Boot 中自定义一个 starter。 1. 创建 Maven 项目 首先&#xff0c;创建一个新的 Maven 项目&#xff…

SpringBoot开启事务日志

一般框架开启日志的方式&#xff1a; 开启某个包下的日志就写该包路径&#xff0c;开启某个类下的日志就写该类路径。

全国首场以AI数字内容风控为主题的大会,开放参会报名中

网易易盾将于2024年7月6日举办一场AI数字内容风控大会&#xff0c;邀请AI产业链的基础层、模型层和应用层的企业代表&#xff0c;科研机构、律所、院校的专家老师&#xff0c;探讨大模型时代下的自由与责任等话题。参会报名链接&#xff1a;https://sourl.cn/vqUU7X&#xff0c…

【计算机毕业设计】基于Springboot的月度员工绩效考核管理系统【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…

HTTP/2 头部压缩 Header Compress(HPACK)详解

文章目录 1. HPACK 的工作原理1.1 静态表1.2 动态表 2. 压缩过程2.1 编码过程2.2 解码过程 3. HPACK 的优势 在HTTP1.0中&#xff0c;我们使用文本的形式传输header&#xff0c;在header中携带cookie的话&#xff0c;每次都需要重复传输几百到几千的字节&#xff0c;这着实是一…

推荐系统-FM模型

参考&#xff1a;推荐系统&#xff08;三&#xff09;Factorization Machines&#xff08;FM&#xff09;_svmmf-CSDN博客 一句话概括下FM&#xff1a;隐式向量特征交叉----类似embedding的思想 LR 如果利用LR做特征的二阶交叉&#xff0c;有&#xff1a; 但这个公式存在显著…

从0开始C++(七):继承

相关文章&#xff1a; 从0开始C&#xff08;一&#xff09;&#xff1a;从C到C 从0开始C&#xff08;二&#xff09;&#xff1a;类、对象、封装 从0开始C&#xff08;三&#xff09;&#xff1a;构造函数与析构函数详解 从0开始C&#xff08;四&#xff09;&#xff1a;作…

香港服务器托管对外贸行业必要性和优势

在当今全球化的经济环境下&#xff0c;外贸企业面临着前所未有的机遇与挑战。其中&#xff0c;服务器托管的选择对于外贸企业的运营效率和市场拓展具有举足轻重的作用。香港服务器&#xff0c;凭借其独特的地理位置、优质的网络环境和卓越的服务性能&#xff0c;一直是外贸企业…

2024年必备的15个免费 SVG 设计资源

在动态设计领域&#xff0c;SVG&#xff08;可缩放矢量图形&#xff09;已成为设计师打造响应迅速、清晰且适应性强的视觉效果的必备工具。 这些设计非常适合幻灯片 PowerPoint 演示文稿、应用程序设计、网站设计、原型设计、社交媒体帖子等。 在这篇文章中&#xff0c;我们将…

这份AI绘画攻略赶紧码住!超适合小白入门的PS AI插件来啦!

有没有小伙伴对AI绘画很感兴趣&#xff0c;但是看到国外的mj和sd总觉得入门困难&#xff01;别担心&#xff0c;米兔挖到一款超级绝的国产PS AI插件&#xff01;适合新手学习&#xff0c;米兔这里还有一份专为小白准备的AI绘画攻略&#xff0c;让你的创意不再受限&#xff01; …

评测|贪吃小猫疯狂长肉,让它停不下嘴的希喂、鲜朗、帕特真实调研

我发现很多铲屎官存在一个误区&#xff0c;认为“进口即是高贵”&#xff0c;过度信赖进口产品。一见到进口宠物粮就冲动购买&#xff0c;甚至对国产品牌持贬低态度&#xff0c;贴上“质量不佳”、“不符合标准”等标签。 为了更深入地了解这一现象&#xff0c;我深入研究了主食…

minio+tusd+uppy搭建文件上传服务

1、docker部署minio、tusd服务 1.1 新建docker-compose.yml minio API: http://ip:9100 minio控制台: http://ip:9101 tus API: http://ip:9102/files/ tus webhooh: http:172.0.0.1:3000/files/webhooh(用户鉴权API) version: 3.7services:minio:image: minio/minio:RELEAS…

工业软件的分类与选择策略:针对中小企业的实际应用考量

工业软件是现代工业体系的“大脑”&#xff0c;已经渗透到几乎所有工业领域的核心环节&#xff0c;是现代产业之“魂”&#xff0c;是制造强国之重器。工业软件通过优化生产流程、实时监控设备状态、实现自动化控制等功能&#xff0c;可以帮助企业显著提升生产效率和质量&#…

python爬虫-爬虫的基础知识储备

爬虫就是一个不断的去抓去网页的程序&#xff0c;根据我们的需要得到我们想要的结果&#xff01;但我们又要让服务器感觉是我们人在通过浏览器浏览不是程序所为&#xff01;归根到底就是我们通过程序访问网站得到html代码&#xff0c;然后分析html代码获取有效内容的过程。下面…