Unity3d windows平台视频录制

简单易用~原理是在unity里按一定的时间间隔截图,然后用ffmpeg.exe去生成视频~~

本代码使用简单,

一、开发时把ffmpeg.exe放在工程目录下,运行exe时放在同目录下。

二、把movieRecord脚本挂在场景中

三、movieRecord.Inst.StartRecord(); 启动

四、录得差不多的时候movieRecord.Inst.StopRecord();停止

五、movieRecord.OnMovieCreateOver 是视频生成结束的回调,传递的参数是生成的视频的位置

下面是代码:

namespace YangXun {
    using UnityEngine;
    using System.Collections;
    using System.Diagnostics;
    using System;
    using System.IO;

    public class movieRecord:MonoBehaviour {

        public static void CreateMovie(string path,string comName,string outFileName) {
            Process p = new Process();
            string curDir = System.Environment.CurrentDirectory;
            p.StartInfo.FileName = curDir + @"/ffmpeg.exe";
            //print(System.Environment.CurrentDirectory + @"/ffmpeg.exe");
            string arg = string.Format("-i {0}/{1}/{2}%d.jpg -r 25 -vcodec mpeg4 {3}", curDir,path, comName, outFileName);
            p.StartInfo.Arguments = arg;//参数
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动
            p.StartInfo.RedirectStandardError = true;//重定向标准错误流
            p.StartInfo.CreateNoWindow = true;
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//输出流的事件
            p.Start();//启动
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();
            p.Dispose();
            if (OnMovieCreateOver != null) {
                OnMovieCreateOver(outFileName);
            }
        }
        private static void Output(object sendProcess, DataReceivedEventArgs output) {
            if (!String.IsNullOrEmpty(output.Data)) {
                UnityEngine.Debug.Log(output.Data);
            }
        }
        int state = -1;
        int rate = 25;

        private static movieRecord inst;
        public static movieRecord Inst {
            get { return inst; }
        }
        public static Action OnMovieCreateOver;
        void Awake() {
            inst = this;
            if (!Directory.Exists("tImg"))
                Directory.CreateDirectory("tImg");
            if (!Directory.Exists("movie"))
                Directory.CreateDirectory("movie");
            curSpan = 1.0f / 25;

            StartCoroutine(Loop());
        }
        public void StartRecord() {
            state = 1;
            Directory.Delete("tImg", true);
            Directory.CreateDirectory("tImg");
        }
        //public void PauseRecord() {
        //    state = 0;
        //}
        public void StopRecord() {
            state = -1;
            index = 0;
            CreateMovie("tImg", "img", string.Format("movie/{0}.mp4",DateTime.Now.ToString("yyyyMMddhhmmss")));
        }
        public void SetRate() { 
        }
        float curSpan = 0;
        float nowTime = 0;
        int index = 0;
        IEnumerator Loop() {
            while (true) {
                yield return new WaitForEndOfFrame();
                if (state == 1) {
                    nowTime += Time.deltaTime;
                    if (nowTime > curSpan) {
                        nowTime = 0;
                        Texture2D t = capTex();
                        //t.Apply();
                        SaveJpg(t, "tImg/img", index);
                        index++;
                        Resources.UnloadUnusedAssets();
                    }
                }
            }
        }

        Texture2D capTex() {
            Texture2D t = new Texture2D(Screen.width, Screen.height);
            t.ReadPixels(new Rect(0,0,Screen.width,Screen.height), 0, 0);
            return t;
        }
        void SaveJpg(Texture2D tex,string comName,int index) {
            var bytes = tex.EncodeToJPG();
            FileStream fs = new FileStream(comName+index+".jpg",FileMode.Create);
            fs.Write(bytes, 0, bytes.Length);
            fs.Flush();
            fs.Close();
        }
    }
}

再下面是测试代码:

using UnityEngine;
using System.Collections;
using YangXun;

public class Test_movieRecord : MonoBehaviour {

    public Transform cube;
	// Use this for initialization
	IEnumerator Start () {
        movieRecord.OnMovieCreateOver = (str) => {
            Debug.Log("生成的视频路径为:"+str);
        };
        movieRecord.Inst.StartRecord();
        yield return new WaitForSeconds(10);
        movieRecord.Inst.StopRecord();
	}
	
	// Update is called once per frame
	void Update () {
        if(cube)
            cube.transform.Rotate(0, 10, 0);
	}
}
效果图:

Unity3d windows平台视频录制_第1张图片

就是这样~~~


2015/11/7 略有修改

namespace YangXun {
    using UnityEngine;
    using System.Collections;
    using System.Diagnostics;
    using System;
    using System.IO;
    using System.Threading;

    public class movieRecord:MonoBehaviour {

        public Func overrideGetTex;
        public Action overrideSaveJPG;
        static Process p;
        static string outFileName;
        public static void CreateMovie(string path,string comName,string outFileName) {
            p = new Process();
            movieRecord.outFileName = outFileName;
            string curDir = System.Environment.CurrentDirectory;
            p.StartInfo.FileName = curDir + @"\ffmpeg.exe";
            DirectoryInfo dir = new DirectoryInfo(curDir + "\\" + path + "\\" + comName);
            FileInfo[] fcount = dir.GetFiles("*.jpg");
            UnityEngine.Debug.Log(fcount.Length);
            int rate = (int)(fcount.Length / 10f);
            //print(System.Environment.CurrentDirectory + @"/ffmpeg.exe");
            //string arg = string.Format("-i {0}/{1}/{2}%d.jpg -r {3} -vcodec mpeg4 {4}", curDir,path, comName,rate, outFileName);
            string arg = string.Format("-f image2 -r {3} -i {0}\\{1}\\{2}%d.jpg -vcodec mpeg4 {4}", curDir, path, comName, rate, outFileName);
            UnityEngine.Debug.LogFormat("-f image2 -r {3} -i {0}\\{1}\\{2}%d.jpg -vcodec mpeg4 {4}", curDir, path, comName, rate, outFileName);
            p.StartInfo.Arguments = arg;//参数
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动
            //p.StartInfo.RedirectStandardError = true;//重定向标准错误流
            p.StartInfo.CreateNoWindow = true;
            //p.ErrorDataReceived += new DataReceivedEventHandler(Output);//输出流的事件
            p.Start();//启动
            //p.BeginErrorReadLine();//开始异步读取
            //p.WaitForExit();//阻塞等待进程结束
            //p.Close();
            //p.Dispose();
            CoroutineWrapper.Inst.OnPerFrame += CheckPExited;
        }
        private static void CheckPExited() {
            if (p.HasExited) {
                OnMovieCreateOver(outFileName);
                CoroutineWrapper.Inst.OnPerFrame -= CheckPExited;
            }
        }
        //
        public static void Mp42Ogg(string path) {
            Process p = new Process();
            string curDir = System.Environment.CurrentDirectory;
            p.StartInfo.FileName = curDir + @"\ffmpeg.exe";

            string outFilePath = path.Replace(".mp4", ".ogg");

            string arg = string.Format("-i {0} -vcodec h263 -r {1} {2}", path, 25, outFilePath);

            p.StartInfo.Arguments = arg;//参数
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动
            p.StartInfo.RedirectStandardError = true;//重定向标准错误流
            p.StartInfo.CreateNoWindow = true;
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//输出流的事件
            p.Start();//启动
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();
            p.Dispose();
            if (OnMovieCreateOver != null) {
                OnMovieCreateOver(outFilePath);
            }
        }
        //
        private static void Output(object sendProcess, DataReceivedEventArgs output) {
            if (!String.IsNullOrEmpty(output.Data)) {
                UnityEngine.Debug.Log(output.Data);
            }
        }
        int state = -1;
        int rate = 25;

        private static movieRecord inst;
        public static movieRecord Inst {
            get {
                if (inst == null) {
                    var obj = new GameObject("movieRecord");
                    inst = obj.AddComponent();
                    inst.overrideGetTex = inst.capTex;
                }
                return inst; 
            }
        }
        public Camera tarCamera;
        public static Action OnMovieCreateOver;
        void Awake() {
            inst = this;
            if (!Directory.Exists("tImg"))
                Directory.CreateDirectory("tImg");
            if (!Directory.Exists("movie"))
                Directory.CreateDirectory("movie");
            curSpan = 1.0f / 25;

            StartCoroutine(Loop());
        }
        public void StartRecord() {
            state = 1;
            Directory.Delete("tImg", true);
            Directory.CreateDirectory("tImg");
        }
        //public void PauseRecord() {
        //    state = 0;
        //}
        public void StopRecord() {
            state = -1;
            index = 0;
            overrideSaveJPG("tImg\\", () => {
                CreateMovie("tImg", "", string.Format("movie\\{0}.mp4", DateTime.Now.ToString("yyyyMMddhhmmss")));
            });
        }
        public void SetRate() { 
        }
        float curSpan = 0;
        float nowTime = 0;
        public int index = 0;
        IEnumerator Loop() {
            while (true) {
                //yield return new WaitForEndOfFrame();
                //if (state == 1) {
                //    nowTime += Time.deltaTime;
                //    if (nowTime > curSpan) {
                //        nowTime = 0;
                //        Texture2D t = capTex();
                //        //t.Apply();
                //        SaveJpg(t, "tImg\\", index);
                //        index++;
                //        Resources.UnloadUnusedAssets();
                //    }
                //}
                yield return new WaitForSeconds(0.04f);
                if (state == 1) {
                    Texture2D t = overrideGetTex();
                    //t.Apply();
                    //SaveJpg(t, "tImg\\", index);
                    index++;
                }
            }
        }

        Texture2D capTex() {
            //Texture2D t = new Texture2D(Screen.width, Screen.height);
            //t.ReadPixels(new Rect(0,0,Screen.width,Screen.height), 0, 0);
            //return t;
            if (tarCamera != null)
                return imgTools.getCamRender(tarCamera, new Rect(0, 0, Screen.width, Screen.height));
            else {
                Texture2D t = new Texture2D(Screen.width, Screen.height);
                t.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
                return t;
            }
        }
        void SaveJpg(Texture2D tex,string comName,int index) {
            var bytes = tex.EncodeToJPG();
            FileStream fs = new FileStream(comName+index+".jpg",FileMode.Create);
            fs.Write(bytes, 0, bytes.Length);
            fs.Flush();
            fs.Close();
        }
    }
}



你可能感兴趣的:(今天天气哈哈哈)