using System.Collections; using System.Collections.Generic; using UnityEngine; using FFmpegOut; using System; using System.Diagnostics; using System.IO; using System.Threading; using UnityEngine.UI; using System.Linq; [RequireComponent(typeof(CameraCapture))] [RequireComponent(typeof(AudioListenerRecorder))] public class MovieRecorder : MonoBehaviour { //the most important is FPS ,take care if u do not want the mistake what happen to the audio and capture is not have synchronization private CameraCapture cameraCapture; private AudioListenerRecorder audioListenerRecord; private bool recording; public bool IsRecord { get { return recording; } } #region Editable properties [SerializeField] private string fileName; [SerializeField] FFmpegPipe.Codec _codec; [SerializeField] public SaveAudio.Savetype saveAudioType; [SerializeField] private float RecordTime; [SerializeField] private bool reservedOriginal; #endregion private float StartRecordTime; public delegate void RecordFinished(); public static event RecordFinished FinishedEvent; #region UI [SerializeField] private RectTransform UIPanel; [SerializeField] private Text InputFileName; [SerializeField] private Text uiRecordTime; [SerializeField] private Toggle recordToggle; [SerializeField] private Dropdown mediaTypeDrop; [SerializeField] private Dropdown audioTypeDrop; [SerializeField] private Text InputWidth; [SerializeField] private Text InputHeight; public string InputfileName { set { fileName = value; } } private bool enableUI = false; #endregion void Awake() { cameraCapture = GetComponent(); audioListenerRecord = GetComponent(); if(UIPanel == null) { UIPanel = GameObject.Find("RecordUICanvas").transform.Find("Panel").GetComponent(); } if(UIPanel != null) { InputFileName = UIPanel.transform.Find("FileName").Find("InputField").GetComponent().textComponent; uiRecordTime = UIPanel.transform.Find("RecordTime").GetChild(0).GetComponent(); recordToggle = UIPanel.transform.Find("RecordToggle").GetComponent(); mediaTypeDrop = UIPanel.transform.Find("MediaTypeDropdown").GetComponent(); audioTypeDrop = UIPanel.transform.Find("AudioTypeDropdown").GetComponent(); InputWidth = UIPanel.transform.Find("width").Find("InputField").GetComponent().textComponent; InputHeight = UIPanel.transform.Find("height").Find("InputField").GetComponent().textComponent; enableUI = false; List mediaTypeOptions = new List(); for (int i=0;i< (int)Enum.GetValues(typeof(FFmpegPipe.Codec)).Cast().Max() + 1;i++) { mediaTypeOptions.Add(new Dropdown.OptionData(((FFmpegPipe.Codec)i).ToString())); } mediaTypeDrop.AddOptions(mediaTypeOptions); //mediaTypeDrop.onValueChanged.AddListener((v) => SetMediaType(v)); List audioTypeOptions = new List(); for (int i = 0; i < (int)Enum.GetValues(typeof(SaveAudio.Savetype)).Cast().Max()+1; i++) { audioTypeOptions.Add(new Dropdown.OptionData(((SaveAudio.Savetype)i).ToString())); } audioTypeDrop.AddOptions(audioTypeOptions); //audioTypeDrop.onValueChanged.AddListener((v) => SetAudioType(v)); } UIPanel.gameObject.SetActive(enableUI); } // Use this for initialization void Start () { recording = false; FinishedEvent += ShowReocrdTime; } // Update is called once per frame void Update () { if(Input.GetKeyDown(KeyCode.R)) { if(!recording) { fileName = DateTime.Now.ToString("yyyy-MMdd-HHmmss"); StartRecord(fileName); } else { StopRecord(); } } if (Input.GetKeyDown(KeyCode.F2)) { enableUI = !enableUI; UIPanel.gameObject.SetActive(enableUI); } if (recording) { CountRecordTime(); } if(enableUI) { recordToggle.isOn = recording; uiRecordTime.text = RecordTime.ToString(); } } void CountRecordTime() { RecordTime = Time.time - StartRecordTime; } public void StartRecord(string filename) { if (recording) return; fileName = filename; StartRecord(); } public void StartRecord() { if (recording) return; if (enableUI) { fileName = InputFileName.text; if(fileName == null || fileName == "") fileName = DateTime.Now.ToString("yyyy-MMdd-HHmmss"); SetMediaType(mediaTypeDrop.value); SetAudioType(audioTypeDrop.value); int width; int height; if (Int32.TryParse(InputWidth.text, out width) && Int32.TryParse(InputHeight.text, out height)) { cameraCapture.SetResolution(width, height); } } recording = true; cameraCapture._codec = _codec; audioListenerRecord.saveAudioType = saveAudioType; cameraCapture.StartCapture("Tempmovie" + fileName); audioListenerRecord.StartRecord("Tempaudio" + fileName); StartRecordTime = Time.time; } public void StopRecord() { if (!recording) return; CountRecordTime(); cameraCapture.StopCapture(); audioListenerRecord.StopRecord(); StartCoroutine(StartCombine()); recording = false; } public void SetMediaType(int i) { _codec = (FFmpegPipe.Codec)i; } public void SetAudioType(int i) { saveAudioType = (SaveAudio.Savetype)i; } IEnumerator StartCombine() { yield return new WaitForSeconds(0.5f); string Arguments = "-i " + "Tempmovie" + fileName + FFmpegPipe.GetSuffix(_codec) + " -i " + "Tempaudio" + fileName + "." + audioListenerRecord.saveAudioType.ToString() + " -c copy -map 0:0 -map 1:0 -ar " + audioListenerRecord.outputRate.ToString() + " " + fileName + FFmpegPipe.GetSuffix(_codec); if (_codec == FFmpegPipe.Codec.H264 && audioListenerRecord.saveAudioType == SaveAudio.Savetype.wav) Arguments = "-i " + "Tempmovie" + fileName + FFmpegPipe.GetSuffix(_codec) + " -i " + "Tempaudio" + fileName + "." + audioListenerRecord.saveAudioType.ToString() + " -c copy -map 0:0 -map 1:0 -acodec mp3 -vcodec copy -ar " + audioListenerRecord.outputRate.ToString() + " " + fileName + FFmpegPipe.GetSuffix(_codec); yield return ExcuteProcess(FFmpegConfig.BinaryPath, Arguments, (s, e) => print(e.Data)); if (!reservedOriginal) { File.Delete(Application.dataPath + "/../Tempmovie" + fileName + FFmpegPipe.GetSuffix(_codec)); File.Delete(Application.dataPath + "/../Tempaudio" + fileName + "." +audioListenerRecord.saveAudioType.ToString()); } if (FinishedEvent != null) FinishedEvent(); } void ShowReocrdTime() { print("RecordTime:" + RecordTime); } IEnumerator ExcuteProcess(string fileName, string arg, DataReceivedEventHandler output) { Thread WriteThread = new Thread(() => _ExcuteProcess(fileName, arg, output)); WriteThread.Start(); while (WriteThread.IsAlive) yield return null; } void _ExcuteProcess(string fileName, string arg, DataReceivedEventHandler output) { using (var p = new Process()) { p.StartInfo.FileName = fileName; p.StartInfo.Arguments = arg; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; p.OutputDataReceived += output; p.ErrorDataReceived += output; p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); p.WaitForExit(); } } }