1. 程式人生 > >.NET讀取視訊資訊、視訊截圖

.NET讀取視訊資訊、視訊截圖

在.NET中處理視訊是一件痛苦的事情,.NET並沒有提供視訊處理的類。於是咱們只能找一些第三方的類庫或者自己實現,在專案時間比較趕的情況下,自己實現是不可能的了,而且說不定會留下很多坑。所以一般情況下,咱們都是找一些靠譜的第三方類庫,畢竟別人確實實現得蠻好的。
這次的專案是一個資訊釋出APP,其中一個模組功能有些類似微信朋友圈,釋出內容需要支援圖片、音訊、視訊等。其他的都很好處理,但視訊的處理著實讓我費了一番勁兒,之前也沒有接觸過視訊處理的專案,甚至對視訊處理的瞭解也挺少的。於是我Google了大半天(國內搜尋引擎很少相關資料,此處建議使用Google Code),找到了一些解決方案,我選取了其中的2個。

1、AVBlocks

不得不說AVBlocks確實是做得挺不錯的,其主要功能是處理視訊、音訊、圖片等多媒體檔案;AVBlocks官網提供了非常詳細的Demo,比較可惜的是Demo的註釋跟說明比較少(或者只是我沒有發現),我在開始工作前把這個Demo裡面38個專案通讀了一遍(基本每個專案只包含一種功能,程式碼簡潔)。

a)功能簡介

主要包括視訊的格式、流、位元率、顏色格式(Color Format)、寬高比、解析度、幀率、掃描方式(Scan Type;這個引數我是真的不認識);

獲取音訊、圖片資訊我還沒用到,不過據官網的介紹看起來還是挺好用的,AVBlocks支援的格式很多,值得一用。

b)使用方法

使用AVBlocks的方法很簡單,直接在你的專案中引用 AVBlocks.clr4.x64.dll ,然後複製 AVBlocks64.dll 到你的專案生成目錄下(如果是 WinForm,則複製到輸出目錄根目錄;如果是 ASP.NET,則複製到輸出目錄 bin 目錄)就可以了。

如果執行時報以下錯誤:
“無法載入 DLL“AVBlocks64.dll”: 找不到指定的模組。 (異常來自 HRESULT:0x8007007E)。”
不用懷疑,肯定是你沒有把AVBlocks64.dll複製到輸出目錄下。

c)上線注意事項

之所以寫這部分是因為我在上線的時候就傻乎乎跳進了一個坑,Windows Server 2008/2008 R2/2012/2012 R2等伺服器預設是沒有安裝wmvcore.dll。這需要我們手動安裝Media Foundation(媒體基礎)或者Desktop Experience(桌面體驗)功能。我選擇安裝“桌面體驗”功能。
大概操作是這樣:伺服器管理器->功能->新增,然後找到“桌面體驗”,勾選、確定,安裝完成後重啟就可以了。

不然會一直報錯“未將物件引用設定到物件的例項”。其實官網有說明,只是我一開始沒留意。

AVBlocks官網說明

下面是這部分的程式碼:


        public class VideoInfo
        {
            //public StreamType Container { get; set; }
            //public int Streams { get; set; }
            public string FileName { get; set; }
            public string CaptureFile { get; set; }
            public MediaType MediaType { get
; set; } public StreamType StreamType { get; set; } public StreamSubType StreamSubType { get; set; } public int Id { get; set; } public double Duration { get; set; } public int Bitrate { get; set; } public BitrateMode BitrateMode { get; set; } public ColorFormat ColorFormat { get; set; } public int DisplayRatioWidth { get; set; } public int DisplayRatioHeight { get; set; } public bool FrameBottomUp { get; set; } public int FrameWidth { get; set; } public int FrameHeight { get; set; } public double FrameRate { get; set; } public ScanType ScanType { get; set; } } public static VideoInfo GetVideoInfo(string inputFile) { VideoInfo videoInfo = new VideoInfo(); using (MediaInfo info = new MediaInfo()) { info.Inputs[0].File = inputFile; if (!info.Open()) { return null; } videoInfo = GetStreams(info)[0]; } // videoInfo.CaptureFile = CatchImg(inputFile, videoInfo.FrameWidth, videoInfo.FrameHeight); return videoInfo; } private static List<VideoInfo> GetStreams(MediaInfo mediaInfo) { List<VideoInfo> videoInfos = new List<VideoInfo>(); foreach (var socket in mediaInfo.Outputs) { VideoInfo videoInfo = new VideoInfo(); for (int streamIndex = 0; streamIndex < socket.Pins.Count; streamIndex++) { StreamInfo si = socket.Pins[streamIndex].StreamInfo; videoInfo.MediaType = si.MediaType; videoInfo.StreamType = si.StreamType; videoInfo.StreamSubType = si.StreamSubType; videoInfo.Id = si.ID; videoInfo.Duration = si.Duration; if (MediaType.Video == si.MediaType) { VideoStreamInfo vsi = si as VideoStreamInfo; videoInfo.Bitrate = vsi.Bitrate; videoInfo.BitrateMode = vsi.BitrateMode; videoInfo.ColorFormat = vsi.ColorFormat; videoInfo.DisplayRatioWidth = vsi.DisplayRatioWidth; videoInfo.DisplayRatioHeight = vsi.DisplayRatioHeight; videoInfo.FrameBottomUp = vsi.FrameBottomUp; videoInfo.FrameWidth = vsi.FrameWidth; videoInfo.FrameHeight = vsi.FrameHeight; videoInfo.FrameRate = vsi.FrameRate; videoInfo.ScanType = vsi.ScanType; } videoInfos.Add(videoInfo); } } return videoInfos; }

2、FFMpeg

在專案中,我需要隨機擷取視訊中其中一幀的圖片作為視訊封面,所以我找到了FFMpeg只是簡單的做個截圖功能。
其實FFMpeg功能很強大,想轉換視訊格式什麼的,推薦大家有興趣讀一下這篇文章:

我簡單介紹下我專案中的使用:

a)複製ffMpeg.exe到系統目錄下,目錄隨意,在第二步進行配置;
b)需在Web.config的appSettings節點中配置ffmpeg.exe的路徑,<add key="ffmpeg" value="plugins\ffmpeg.exe" />;
c)上程式碼;


        /// <summary>
        /// 使用ffMpeg.exe擷取視訊圖片(第一幀)
        /// *需在Web.config的appSettings節點中配置ffmpeg.exe的路徑*
        /// *<add key="ffmpeg" value="plugins\ffmpeg.exe" />*
        /// </summary>
        /// <param name="vedioPath">視訊路徑</param>
        /// <param name="saveImgWidth">儲存的圖片寬度</param>
        /// <param name="saveImgHeight">儲存的圖片高度</param>
        /// <returns>儲存後的圖片路徑(去除基路徑)</returns>
        public static string CatchImg(string vedioPath, int saveImgWidth, int saveImgHeight)
        {
            string ffmpeg = AppDomain.CurrentDomain.BaseDirectory + "\\" + System.Configuration.ConfigurationSettings.AppSettings["ffmpeg"];
            if ((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(vedioPath)))
            {
                return "";
            }

            string saveImgPath = System.IO.Path.ChangeExtension(vedioPath, ".jpg");
            string saveImgSize = string.Format("{0}x{1}", saveImgWidth, saveImgHeight);
            ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg);
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.Arguments = string.Format(" -i \"{0}\" -y -f image2 -t 0.001 -s \"{1}\" \"{2}\"", vedioPath, saveImgSize, saveImgPath);
            System.Diagnostics.Process.Start(startInfo);

            return saveImgPath.Replace(AppDomain.CurrentDomain.BaseDirectory, "");
        }

以上就是這次我關於.NET視訊處理的一些經驗。

最後附上這個類的完整程式碼:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using PrimoSoftware.AVBlocks;

namespace JHD.Utils
{
    public class AvInfoUtil
    {
        public class VideoInfo
        {
            //public StreamType Container { get; set; }
            //public int Streams { get; set; }
            public string FileName { get; set; }
            public string CaptureFile { get; set; }
            public MediaType MediaType { get; set; }
            public StreamType StreamType { get; set; }
            public StreamSubType StreamSubType { get; set; }
            public int Id { get; set; }
            public double Duration { get; set; }
            public int Bitrate { get; set; }
            public BitrateMode BitrateMode { get; set; }
            public ColorFormat ColorFormat { get; set; }
            public int DisplayRatioWidth { get; set; }
            public int DisplayRatioHeight { get; set; }
            public bool FrameBottomUp { get; set; }
            public int FrameWidth { get; set; }
            public int FrameHeight { get; set; }
            public double FrameRate { get; set; }
            public ScanType ScanType { get; set; }
        }

        public static VideoInfo GetVideoInfo(string inputFile)
        {
            VideoInfo videoInfo = new VideoInfo();
            using (MediaInfo info = new MediaInfo())
            {
                info.Inputs[0].File = inputFile;

                if (!info.Open())
                {
                    return null;
                }

                videoInfo = GetStreams(info)[0];
            }

            videoInfo.CaptureFile = CatchImg(inputFile, videoInfo.FrameWidth, videoInfo.FrameHeight);

            return videoInfo;
        }

        private static List<VideoInfo> GetStreams(MediaInfo mediaInfo)
        {
            List<VideoInfo> videoInfos = new List<VideoInfo>();
            foreach (var socket in mediaInfo.Outputs)
            {
                VideoInfo videoInfo = new VideoInfo();

                for (int streamIndex = 0; streamIndex < socket.Pins.Count; streamIndex++)
                {
                    StreamInfo si = socket.Pins[streamIndex].StreamInfo;
                    videoInfo.MediaType = si.MediaType;
                    videoInfo.StreamType = si.StreamType;
                    videoInfo.StreamSubType = si.StreamSubType;
                    videoInfo.Id = si.ID;
                    videoInfo.Duration = si.Duration;

                    if (MediaType.Video == si.MediaType)
                    {
                        VideoStreamInfo vsi = si as VideoStreamInfo;
                        videoInfo.Bitrate = vsi.Bitrate;
                        videoInfo.BitrateMode = vsi.BitrateMode;
                        videoInfo.ColorFormat = vsi.ColorFormat;
                        videoInfo.DisplayRatioWidth = vsi.DisplayRatioWidth;
                        videoInfo.DisplayRatioHeight = vsi.DisplayRatioHeight;
                        videoInfo.FrameBottomUp = vsi.FrameBottomUp;
                        videoInfo.FrameWidth = vsi.FrameWidth;
                        videoInfo.FrameHeight = vsi.FrameHeight;
                        videoInfo.FrameRate = vsi.FrameRate;
                        videoInfo.ScanType = vsi.ScanType;
                    }

                    videoInfos.Add(videoInfo);
                }
            }
            return videoInfos;
        }

        /// <summary>
        /// 使用ffMpeg.exe擷取視訊圖片(第一幀)
        /// *需在Web.config的appSettings節點中配置ffmpeg.exe的路徑*
        /// *<add key="ffmpeg" value="plugins\ffmpeg.exe" />*
        /// </summary>
        /// <param name="vedioPath">視訊路徑</param>
        /// <param name="saveImgWidth">儲存的圖片寬度</param>
        /// <param name="saveImgHeight">儲存的圖片高度</param>
        /// <returns>儲存後的圖片路徑(去除基路徑)</returns>
        public static string CatchImg(string vedioPath, int saveImgWidth, int saveImgHeight)
        {
            string ffmpeg = AppDomain.CurrentDomain.BaseDirectory + "\\" + System.Configuration.ConfigurationSettings.AppSettings["ffmpeg"];
            if ((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(vedioPath)))
            {
                return "";
            }

            string saveImgPath = System.IO.Path.ChangeExtension(vedioPath, ".jpg");
            string saveImgSize = string.Format("{0}x{1}", saveImgWidth, saveImgHeight);
            ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg);
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.Arguments = string.Format(" -i \"{0}\" -y -f image2 -t 0.001 -s \"{1}\" \"{2}\"", vedioPath, saveImgSize, saveImgPath);
            System.Diagnostics.Process.Start(startInfo);

            return saveImgPath.Replace(AppDomain.CurrentDomain.BaseDirectory, "");
        }
    }
}

相關推薦

.NET讀取視訊資訊視訊

在.NET中處理視訊是一件痛苦的事情,.NET並沒有提供視訊處理的類。於是咱們只能找一些第三方的類庫或者自己實現,在專案時間比較趕的情況下,自己實現是不可能的了,而且說不定會留下很多坑。所以一般情況下,咱們都是找一些靠譜的第三方類庫,畢竟別人確實實現得蠻好的。

ADO.Net中DataSet的應用(知識點描述思維導示例程式碼效果

一.知識點描述 ADO.NET是Microsoft公司推出的.NET框架中用於資料訪問的元件,ADO. NET是.Net FrameWork SDK 中用以操作資料庫的類庫的總稱。而DataSet 類則是ADO. NET中最核心的成員之一,也是各種開發基於.Net平臺程式語言開發資料庫應用程式最常接觸的類。

ffmpeg處理視訊獲取第一幀

<?php //使用PHP SDK,並且使用自定義配置檔案 require app_path().'/include/BaiduBce.phar'; require app_path().'/include/SampleConf.php'; require app_path().'

ADO.Net中DataTable的應用(知識點描述思維導示例程式碼效果

SqlConnection sqlConnection = new SqlConnection(); //宣告並例項化SQL連線; sqlConnection.ConnectionString

【JAVA】JAVA使用ffmpeg進行視訊格式轉換以及

JAVA 處理視訊檔案,需要用到 ffmpeg  這個工具。不需要依賴jar包。無論是在windows伺服器還是linux伺服器,想要使用 ffmpeg 都需要先安裝。 附上Linux下  *.tar.gz/*.tgz、*.bz2形式的原始碼軟體包    安裝方法:

使用AForge.NET Framework打開攝像頭並 C#

int mon info bit sta pla red 說了 player videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); if

【Tools】macOS 工具推薦xnip(滾動&步驟

20181113截圖工具先用了騰訊的snip,滾動截圖我在chrome和別的軟體下測試下沒成功。而且需要修改輔助功能。 xnip實現的原理似乎是滑鼠滾動時軟體自己拼接圖片。 此外,xnip的步驟截圖非常驚豔。 這兩個功能是很多截圖軟體都沒有的。 參考:https://

微信視訊應用視訊直播流媒體服務視訊教學線上教育類原創文章彙總

原創文章 / 阿酷TONY / 更新:2018-12-12 長沙 / 陽光明媚 / yáng guāng míng mèi /  2 ~ 6℃ 微信視訊應用、視訊直播、流媒體服務、視訊教學、線上教育類原創文章彙總 (2017-2018年度) &nbs

基於WebRtc在H5視訊聊天視訊教學視訊會議視訊直播白板互動低延時方案

隨移動互聯應用加快,4G,5G網路上馬,低延時網路視訊應改越來越走近生活,在教學,會議,線上醫療,招聘交友及時視訊要求高等場景需求越來越大,傳統基於rtmp直播應用已經大量應用在各個方向,由於rtmp基於TCP延時上可控較差,有積累延時,互動效能差,而新興的Webrtc技術,

安卓獲取視訊時間視訊寬高

private String getPlayTime(String mUri) { android.media.MediaMetadataRetriever mmr = new android.media.MediaMetadataRetriever(); tr

Spring Boot + MyBatis 電商專案 -04- 使用 Spring MVC 讀取使用者資訊篩選欄位

Spring Boot + MyBatis 電商專案 -04- 使用 Spring MVC 讀取使用者資訊、篩選欄位 前幾篇文章: (如果不是新手,建議至少看完第 3 篇,因為整個專案是基於第三篇建立的很多檔案進行的) Spring Boot + MyBatis 電商

java 視訊會議視訊溝通遠端教育java視訊會議系統

以下都是基於webrtc的實現 方案1:簡單版 基於js框架 http://www.rtcmulticonnection.org/ 只要安裝好後臺的服務即可 體驗地址:https://github.com/muaz-khan/RTCMultiConnection#v3-de

springboot讀取配置資訊環境變數

2、讀取配置檔案2.1 讀取核心配置檔案核心配置檔案是指在resources根目錄下的application.properties或application.yml配置檔案,讀取這兩個配置檔案的方法有兩種,都比較簡單。核心配置檔案application.properties內容

視訊互動視訊會議語音對講IM開戶等軟體的基本流程和開發指南

視訊呼叫業務邏輯主要實現兩個終端(PC、手機、Pad等)之間的通話請求流程控制,包括請求(Request)、回覆(Reply)、開始(Start)以及結束(Finish)等過程,可以形象理解為打電話的流程:撥號、等待、通話、結束通話。      以下以AnyChat視訊

小程式填坑之路—讀取使用者資訊快取其資料讀取其資料(buttonwx.setStoragewx.getStorage)

        深深以為,遇見一個好的文章不容易,希望自己也能用心填坑。         首先來說讀取使用者資訊,之前是用getUserInfo(),但在2018年4月30日之後,該介面不適用於開發版和測試版,正式上線的小程式不受影響。很不幸,我就是4月30後後的這批。出於

PHP後臺自動獲取視訊資訊功能例項

名稱:php自動獲取視訊資訊並截圖 描述:PHP後臺自動獲取視訊資訊並截圖功能例項,包含ffmpeg的安裝步驟。 版本:所有版本 步驟1:確保 shell_exec() 函式是否可用!,php.ini中修改下方禁用函式。 disable_functions = pa

Android中如何獲取視訊檔案的

背景 公司最近要求給我負責的APP加上視訊錄製和釋出的功能,我簡單的完成了基本的錄製和視訊壓縮功能,後來發現釋出介面需要上傳視訊的截圖,網上搜索了一下資料,在這裡整理一下。 程式碼實現 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

使用ffmpeg視訊格式轉換視訊視訊採集螢幕錄製

ffmpeg.exe-i F:閃客之家閃客之歌.mp3 -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:11.flv ffmpeg -i F:01.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:test.flv 使用-ss引

7實現指令碼執行失敗 時自動並儲存出錯資訊到檔案中

自動化指令碼如果失敗了,憑藉什麼去快速定位呢?當然是截圖和出錯資訊了,這裡就來實現這兩個功能。 方法是重寫TestListenerAdapter中的onTestFailure和onTestSkipped方法,在方法中新增截圖和儲存出錯資訊到文字的方法。 新建一個webtestListener.j

springboot中配置addResourceHandler和addResourceLocations,使得可以從磁碟中讀取圖片視訊音訊等

磁碟目錄 WebMvcConfig的程式碼 //對靜態資源的配置 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String os = System.ge