二、实践与视频解决方案

article/2025/11/7 19:23:21

一、视频解决方案

说明:

公司下户拍摄视频,上传存储一直用的优酷云(视频压缩、解码、播放)当然还支持水印。

现在场景,我们公司内部买服务器,下户拍摄视频上传到我们自己服务内,需要解决的问题,下户拍摄视频很大,需要解决的问题:

1、(下户视频过大)需要压缩处理、

2、(视频格式、播放帧处理)解码格式

3、(提供url)提供接口让内部人员可以播放

 

 解决方案1、亲测

使用官网:ffmpeg 、GitHub:https://github.com/FFmpeg/FFmpeg

 

 

 

 

在下载页面上,我们可以看到,对于32位和64位版本,分别提供了三种不同的模式:static、shared和dev

  • static: 该版本提供了静态版本的FFmpeg工具,将依赖的库生成在了最终的可执行文件中;作为工具而言此版本就可以满足我们的需求;
  • share: 该版本的工具包括可执行文件和dll,程序运行过程必须依赖于提供的dll文件;
  • dev: 提供了库的头文件和dll的引导库;

 

这里下载的是static版本,将其下载解压到项目目录下:

C#代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ffmpeg
{class Program{static string FFmpegPath = @"C:\Users\Bruce\source\repos\ffmpeg\ffmpeg\bin\Debug\ffmpeg-20190820-74e6800-win64-static\bin\ffmpeg.exe";static void Main(string[] args){string videoUrl = @"D:\video\Wildlife.wmv";string targetUrl = @"D:\video\newFile.mp4";//视频转码string para = string.Format("-i {0} -b 1024k -acodec copy -f mp4 {1}", videoUrl, targetUrl);RunMyProcess(para);Console.WriteLine("完成!");Console.ReadKey();}static void RunMyProcess(string Parameters){var p = new Process();p.StartInfo.FileName = FFmpegPath;p.StartInfo.Arguments = Parameters;//是否使用操作系统shell启动p.StartInfo.UseShellExecute = false;//不显示程序窗口p.StartInfo.CreateNoWindow = true;p.Start();Console.WriteLine("\n开始转码...\n");p.WaitForExit();p.Close();p.Dispose();//释放资源
        }}
}

引入exe文件

但是由于ffmpeg视频转码,转码完成后程序一直卡死且一直未收到exit消息,

原因是ffmpeg是StandardError流,要读取StandardError而不是StandardOutput。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ffmpeg
{class Program{static string FFmpegPath = @"C:\Users\Bruce\source\repos\ffmpeg\ffmpeg\bin\Debug\ffmpeg-20190820-74e6800-win64-static\bin\ffmpeg.exe";static void Main(string[] args){string videoUrl = @"D:\video\Wildlife.mp4";string targetUrl = @"D:\video\newFile2.mp4";//视频转码string para = string.Format("-i {0} -r 10 -b:a 32k {1}", videoUrl, targetUrl);RunMyProcess(para);Console.WriteLine("转码结束时间:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\n完成!");Console.ReadKey();}static void RunMyProcess(string Parameters){var p = new Process();p.StartInfo.FileName = FFmpegPath;p.StartInfo.Arguments = Parameters;//是否使用操作系统shell启动p.StartInfo.UseShellExecute = false;//不显示程序窗口p.StartInfo.CreateNoWindow = true;p.StartInfo.RedirectStandardError = true;//重定向标准错误输出p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();p.BeginErrorReadLine();//开始异步读取Console.WriteLine("转码开始时间:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "\n开始转码...\n");p.WaitForExit();//阻塞等待进程结束p.Close();//关闭进程p.Dispose();//释放资源
        }private static void Output(object sendProcess, DataReceivedEventArgs output){if (!String.IsNullOrEmpty(output.Data)){//处理方法...Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")+":" +output.Data);}}}
}

2、视频大小信息

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ffmpeg
{class Program{static string FFmpegPath = @"C:\Users\Bruce\source\repos\ffmpeg\ffmpeg\bin\Debug\ffmpeg-20190820-74e6800-win64-static\bin\ffmpeg.exe";static void Main(string[] args){string videoUrl = @"D:\video\Wildlife.MP4";//视频转码int time = GetVideoDuration(FFmpegPath, videoUrl);Console.WriteLine("视频时间:" + time + "");Console.ReadKey();}private static int GetVideoDuration(string ffmpegfile, string sourceFile){try{using (System.Diagnostics.Process ffmpeg = new System.Diagnostics.Process()){String duration;  // soon will hold our video‘s duration in the form "HH:MM:SS.UU"  String result;  // temp variable holding a string representation of our video‘s duration  StreamReader errorreader;  // StringWriter to hold output from ffmpeg  // we want to execute the process without opening a shell  ffmpeg.StartInfo.UseShellExecute = false;//ffmpeg.StartInfo.ErrorDialog = false;  ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;// redirect StandardError so we can parse it  // for some reason the output comes through over StandardError  ffmpeg.StartInfo.RedirectStandardError = true;// set the file name of our process, including the full path  // (as well as quotes, as if you were calling it from the command-line)  ffmpeg.StartInfo.FileName = ffmpegfile;// set the command-line arguments of our process, including full paths of any files  // (as well as quotes, as if you were passing these arguments on the command-line)  ffmpeg.StartInfo.Arguments = "-i " + sourceFile;// start the process  
                    ffmpeg.Start();// now that the process is started, we can redirect output to the StreamReader we defined  errorreader = ffmpeg.StandardError;// wait until ffmpeg comes back  
                    ffmpeg.WaitForExit();// read the output from ffmpeg, which for some reason is found in Process.StandardError  result = errorreader.ReadToEnd();// a little convoluded, this string manipulation...  // working from the inside out, it:  // takes a substring of result, starting from the end of the "Duration: " label contained within,  // (execute "ffmpeg.exe -i somevideofile" on the command-line to verify for yourself that it is there)  // and going the full length of the timestamp  duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00").Length);string[] ss = duration.Split(':');int h = int.Parse(ss[0]);int m = int.Parse(ss[1]);int s = int.Parse(ss[2]);return h * 3600 + m * 60 + s;}}catch (System.Exception ex){return 60;}}}
}

 

 

 

3、视频进度百分比

 

 

 

 

 代码  转码进度公式=当前时间/总时间*100

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ffmpeg
{class Program{static void Main(string[] args){FFmpeg.Execute();Console.ReadKey();}}public class FFmpeg{static int timeCount;public static void Execute(){string ffmpegPath = @"C:\Users\Bruce\source\repos\ffmpeg\ffmpeg\bin\Debug\ffmpeg-20190820-74e6800-win64-static\bin\ffmpeg.exe";Process p = new Process();p.StartInfo.FileName = ffmpegPath;p.StartInfo.UseShellExecute = false;string videoUrl = @"D:\video\_Wildlife.mp4";string targetUrl = @"D:\video\newFile15.mp4";//视频转码string para = string.Format("-i {0} -r 10 -b:a 32k {1}", videoUrl, targetUrl);p.StartInfo.Arguments = para;  //执行参数//-i D:/vts-collector/test/swap/7a3c9800-2e2f-42fe-ba39-56b25f972e06.mov -y -ab 56 -ar 22050 -b 800 -r 29.97 -s 420x340 D:/vts-collector/test/swap/7a3c9800-2e2f-42fe-ba39-56b25f972e06_mov_stream.mp4p.StartInfo.RedirectStandardInput = true;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);using (p){p.Start();p.BeginErrorReadLine();//开始异步读取p.WaitForExit();//阻塞等待进程结束p.Close();//关闭进程
            }}private static void p_ErrorDataReceived(object sender, DataReceivedEventArgs e){var output = e.Data;if (output != null){if (output.Contains("Duration")){Int32 indexOfDuration = output.IndexOf("Duration");Int32 indexOfBegin = output.IndexOf(":", indexOfDuration);Int32 indexOfEnd = output.IndexOf(",", indexOfBegin);var duration = output.Substring(indexOfBegin + 1, indexOfEnd - indexOfBegin - 1);timeCount = ConvertStringtoSecond(duration);}if (output.Contains("time=")){Int32 indexOfTime = output.IndexOf("time=");Int32 indexOfBegin = output.IndexOf("=", indexOfTime);Int32 indexOfEnd = output.IndexOf("bitrate", indexOfBegin);string timeStr = output.Substring(indexOfBegin + 1, indexOfEnd - indexOfBegin - 1);//
                    var time = Convert.ToDouble(ConvertStringtoSecond(timeStr));//
                    var process = time / timeCount * 100;  //当前毫秒单位process = Math.Round(process);Console.Write("{0}% ", process);}//Console.WriteLine(e.Data);
            }}private static int ConvertStringtoSecond(string timeStr){int totalSecond = 0;try{DateTime dateTime = Convert.ToDateTime(timeStr);totalSecond = dateTime.Hour * 3600000 + dateTime.Minute * 60000 + dateTime.Second * 1000 + dateTime.Millisecond;}catch (System.Exception ex){Console.Write(ex.Message);}return totalSecond;}private static void p_OutputDataReceived(object sender, DataReceivedEventArgs e){Console.WriteLine(e.Data);}}}

 

 

4、视频转码其他指令

string para = string.Format("-i {0} -b:v 400k -s 1920*1080 {1}", videoUrl, targetUrl);   //模糊不清楚,1920*1080 完全行不通 很模糊
string para = string.Format("-i {0}  {1}", videoUrl, targetUrl);   //3.67G转换后1.06G  简单压缩方式

截图

ffmpeg.exe -i D:\video\Wildlife.MP4 -ss 5 -vframes 1 D:\video\img.jpg  //截图

把视频的前30帧转换成一个Animated Gif

ffmpeg.exe -i D:\video\_Wildlife.MP4 -vframes 30 -y -f gif D:\video\.gif

 水印

//加水印:
ffmpeg -i D:\video\newFile2.mp4 -i D:\video\img.jpg -filter_complex overlay D:\video\__Wildlife.MP4

 参数

说明:LogoName为图片名,overlay=100:100意义为overlay=x:y,在(x,y)坐标处開始加入水印。

         左上角:overlay=10:10 

         右上角:overlay=main_w-overlay_w-10:10

         左下角:overlay=10:main_h-overlay_h-10 

         右下角:overlay=main_w-overlay_w-10:main_h-overlay_h-10

 

//gif图到左下角视频中,经常看视频,类似那些视频广告gif 
ffmpeg -y -i D:\video\newFile2.mp4 -ignore_loop 0 -i D:\video\timg.gif  -filter_complex overlay=0:H-h D:\video\__Wildlife.MP4

 

 

4、论坛说明

http://bbs.chinaffmpeg.com

 

这里下载的是dev版本,将其下载解压到项目目录下:

不是很方便调用,就采用 

FFmpeg.AutoGen

 一、项目搭建nuget添加ffmpeg.autogen引用。

 

 

 

 

转载于:https://www.cnblogs.com/fger/p/11387491.html


http://chatgpt.dhexx.cn/article/SNA38UsI.shtml

相关文章

Servlet应用——JavaWeb教案(四)

文章目录 JavaWeb组件1. ServletRequest1. 介绍Request体系**获取请求消息数据****获取请求行**获取请求头获取超链接的所有头信息防盗链操作 获取请求体 其他功能1. 获取请求参数通用方式2. 请求转发:1. 转发给servlet2. 转发给jsp页面 3. 共享数据1. 转发给servlet2. 转发给J…

20201006将音频为48kHz采样率的mp4转为44.1kHz的步骤

20201006将音频为48kHz采样率的mp4转为44.1kHz的步骤 千千静听v5.1.0 MKVToolNix v48.0 MediaInfo 0.7.86 Copyright (c) MediaArea.net SARL 支持多种格式的多媒体文件: Matroska, OGG (包括 OGM) MPEG-1 (包括 VCD) MPEG-2 (包括 DVD, SVCD) MPEG-4 (包括 iTunes M4A…

怎么讲计算机屏幕录制,电脑如何录制屏幕

电脑如何录制屏幕 腾讯视频/爱奇艺/优酷/外卖 充值4折起 电脑如何录制屏幕呢?如果我们的电脑上有自带的屏幕录制软件,点击即可录制,若没有,我们可以借助QQ来进行录制屏幕,一起来看看吧。 1. 首先打开电脑上的QQ APP: 2. 进入登录页面,输入账号和密码,进行登录: 3. 然后…

免费视频制作工具满足非专业用户的视频处理需求:压缩视频、转码视频、倒放视频、合并片段、根据字幕裁切片段、自动配字幕、自动剪辑等

免费视频制作工具满足非专业用户的视频处理需求:压缩视频、转码视频、倒放视频、合并片段、根据字幕裁切片段、自动配字幕、自动剪辑等。有了它你也可以做出优秀的视频啦~ Quick Cut 是一款轻量、强大、好用的视频处理软件。它是一个轻量的工具&#xf…

win10访问不了服务器的共享文件,win10访问不了samba共享文件夹怎么办

win10访问不了samba共享文件夹怎么办 腾讯视频/爱奇艺/优酷/外卖 充值4折起 最近很多网友反映win系统升级后,访问不了smb服务器,弹出如下图的提示窗,遇到这个问题怎么办呢?下面一起来看看win10访问不了samba共享文件夹的解决方法。 具体如下: 1. 第一步,右键点击桌面左下…

php twitter 登陆sdk,使用Twitter OAuth(PHP)登录Twitter的问题

好吧,我正在尝试使用Twitter API做一个非常简单的登录脚本。我需要的只是让用户通过Twitter登录网站的一种简单方法。如果他们目前没有登录,我的主页上有一个按钮,显示“登录或注册Twitter”。如果他们已登录,我希望它显示他们的用…

用R对Twitter用户的编程语言语义分析

Twitter是一个流行的社交网络,这里有大量的数据等着我们分析。Twitter R包是对twitter数据进行文本挖掘的好工具。最近我们被客户要求撰写关于Twitter的研究报告,包括一些图形和统计输出。本文是关于如何使用Twitter R包获取twitter数据并将其导入R&…

前端javascript如何分享内容到twitter和Email

接着上篇讲,上篇讲了如何分享到facebook,这篇我们讲一下如何分享到twitter和Email,首先分享到twitter和Email不像分享到facebook一样可以有回调,这两分享是没有回调的,分享成功失败,也不知道,但是会触发事件. 我们先来看下分享到twitter,首先引入twitter的sdk文件,如下图所示:…

Twitter数据获取

推文获取 申请Twitter API 注册Twitter账号https://dev.twitter.com/apps, 点击create apps。点击确定完成在Application Management的Keys and Access Tokens,点击Generate Access Token. 利用tweepy获取特朗普最近推文 # -*- coding: utf-8 -*- ""&…

推特 我们目前不能注册此邮箱地址_英雄联盟手游来了!最简单的下载/安装/注册教程!...

从英雄联盟手游的消息至今,已经过去这么多天,想必大家早已等不及想要玩上一把了。等了这么久,如今终于在海外公测了,虽然目前国服还不能游玩,但是跟着本篇教程,你也可以轻松玩到海外版本! 苹果用户看这里: 首先得告知下大家,目前只有Android端开放了内测,使用苹果的小…

Twitter群推王:推特全方位营销利器

Twitter群推王是专为Twitter运营提供的一款全方位营销工具,可以自动发帖、自动私信、自动转发、自动关注、自动点赞、自动改资料、自动注册、数据采集等,解决营销中的三大难题:账号问题、同一Ip环境问题、批量自动化问题,是个人、…

Twitter上热门的技巧与思路

Twitter是一个单向的信息输出平台,更具有时效性、新闻性,因此帖子营销深受用户的喜爱,那么品牌如何玩转帖子营销,从众多的推文中脱颖而出呢? 1、账号 数量上: 对于做SNS营销而言,都是需要大量…

android twitter 分享代码,Twitter分享集成

最近老大要求做下Twitter分享功能,当时我是一脸懵逼的,去看下Twitter的api更加的一脸懵逼。全英文,没看到中文的。然后各自搜索。还是没搞定。还是得去看官方的!那就看吧,索性是搞定了。记录下以方便后查阅。 第一步: 先注册Twitter账号,然后进行相应的设置。 第二步: …

Twitter 用户推文时间线爬虫

0x00 前言 上篇分享了如何申请到Twitter api,申请到twitter API后就可以进行爬虫啦!这里分享一下如何使用API对用户推文时间线爬虫 Twitter 是有分享如何使用API爬虫的python代码的,但是具体如何使用,以及各种参数如何设置需要用…

twitter注册不了_如何阻止Twitter重点阻止不相关的通知

twitter注册不了 Social networks are always trying to get you to “engage” more with their service and recently, Twitter has introduced a new trick: Highlights notifications. 社交网络一直在努力让您与他们的服务“互动”,最近,Twitter引入…

语义识别

文章目录 前言二、案例1.《大雪阳沈东北》2.《青成城山都》 结论 前言 我是个话说逻不辑混乱的,长短对话经常别人听不被懂。短句慢说却是交流无碍,例如“回吃饭家”,“灶房在烧火”。以下测试了下百度和360能否听懂我说话,测试内…

语义搜索

语义搜索简介 目录 语义搜索简介 文档检索 vs. 数据检索 语义模型 语义数据搜索 语义Web——数据Web 利用链接数据进行搜索 存储和索引 (Semplore) 排序原则 如何将排序紧密结合到基本操作中? ​ 从DBpedia收集的混合的查询数据集 为图结构数据(RDF)建立结构…

自然语言处理NLP(10)——语义分析

在上一部分中,我们介绍了句法分析中的局部句法分析以及依存关系分析(自然语言处理NLP(9)——句法分析c:局部句法分析、依存关系分析),至此,繁复冗长的句法分析部分就结束了。 在这一…

语义网络 - 语义网络

语义网络 - 语义网络 编辑本段 回目录 语义网络 - 正文 用于表示知识和建立认知模型的一种带标号的有向图。在语义网络中,带标号的节点表示思考对象──具体事物、抽象概念、状态和局势等;带标号的有向弧则表示节点所代表对象间的关系。语义网络中每一条…

语义表示法

思路方案 在安全领域的研究中我们发现,很多数据预处理的步骤,在不同的场景下中都可以相互 借鉴,甚至可以进行直接复用。例如,对于加密流量相关的数据,当算法工程师 获取到一批加密流量的 pcap 包之后,不论他…