[WPF] ffmpeg을 활용한 동영상 만들기Frontend/WPF2022. 10. 3. 20:24
Table of Contents
반응형
FFmpeg Build 다운로드하기
https://ffmpeg.org/download.html#build-windows 사이트에서 Windows EXE Files 항목의 원하는 형식으로 다운로드를 합니다.
다운로드한 후 압축해제 합니다. 프로젝트의 ffmpeg 폴더를 생성 후 실행에 사용되는 exe, dll 파일들을 복사합니다.
Bitmap들을 동영상으로 만들기
FFmpegLoader
ffmpeg를 사용하기 위해 FFMediaToolkit 패키지를 Nuget을 이용하여 설치합니다. FFmpegLoader
를 사용하여 Path를 지정합니다.
// 예
FFmpegLoader.FFmpegPath = @".\ffmpeg";
동영상에 프레임 추가
아래는 예제코드입니다. StartRecordVideo
함수에 저장될 경로를 지정하여 mediaFile
을 생성합니다. 그리고 AddRecordFrame
함수를 통해 Bitmap
이미지를 설정한 30fps로 동영상에 추가합니다. 이렇게 생성된 동영상은 MPEG2 형식이므로 MPEG4 형식으로 변경합니다. MPEG2 형식의 동영상은 가끔 윈도우 환경에서 오류가 발생하는 경우가 있습니다.
using FFMediaToolkit;
using FFMediaToolkit.Encoding;
using FFMediaToolkit.Graphics;
namespace Hgko.Utils
{
public class ImageService
{
private bool ffmpegInit = false;
private MediaOutput mediaFile = null;
/// <summary>
/// Start Record video
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public void StartRecordVideo(string path)
{
if (mediaFile == null)
{
if (!ffmpegInit)
{
FFmpegLoader.FFmpegPath = @".\ffmpeg";
ffmpegInit = true;
}
int width = 1024;
int heigth = 1024;
VideoEncoderSettings settings = new VideoEncoderSettings(width, heigth, 30, VideoCodec.MPEG2);
settings.EncoderPreset = EncoderPreset.Medium;
mediaFile = MediaBuilder.CreateContainer(path).WithVideo(settings).Create();
}
}
/// <summary>
/// Add RecordFrame
/// </summary>
/// <param name="bitmap"></param>
public void AddRecordFrame(Bitmap bitmap)
{
if (bitmap == null)
return;
if (mediaFile == null)
return;
System.Drawing.Imaging.BitmapData bdata = bitmap.LockBits(new Rectangle(System.Drawing.Point.Empty, bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, bitmap.PixelFormat);
ImageData imgdata = ImageData.FromPointer(bdata.Scan0, ImagePixelFormat.Bgra32, bitmap.Size);
mediaFile.Video.AddFrame(imgdata);
bitmap.UnlockBits(bdata);
}
/// <summary>
/// Stop Record Video
/// </summary>
public void StopRecordVideo()
{
if (mediaFile != null)
{
mediaFile.Video.Dispose();
mediaFile.Dispose();
mediaFile = null;
}
}
}
}
동영상 포맷 변환
임시로 빌드되는 경로에 display/video 경로의 폴더를 생성합니다. 포맷 변환하는 방법은 많습니다. 아래 코드는 여러 이미지 또는 동영상을 합쳐서 새로운 동영상으로 만드는 형식의 방법을 활용하여 포맷 변환을 진행합니다.
using System.IO;
/// <summary>
/// End Record Video
/// </summary>
/// <param name="mp2Path">mp2 형식으로 저장된 파일경로</param>
public void EndRecordVideo(string mp2Path)
{
string videoWorkingPath = @".\display\video\";
string vedeoWorkingFolder = Directory.GetCurrentDirectory() + videoWorkingPath.Replace(".", "");
string outputVeideoPath = vedeoWorkingFolder + Path.GetFileNameWithoutExtension(mp2Path) + ".mp4"
// if exist video working directory, clean up.
if (Directory.Exists(videoWorkingPath))
ClearFolder(videoWorkingPath);
// remake working dir.
Directory.CreateDirectory(videoWorkingPath);
Task.Run(() =>
{
string lstPath = vedeoWorkingFolder + "lst.txt";
// 텍스트 파일에 앞에서 생성된 mp2 동영상 파일 경로 추가
using (StreamWriter writer = File.CreateText(lstPath))
{
writer.WriteLine("file '{0}'", mp2Path);
}
// h264 or mpeg4
string codec = "h264";
// 동영상 포맷 변환(mp2 -> mp4)
string arg = $@"-safe 0 -f concat -i ""{lstPath}"" -c copy -vcodec ""{codec}"" ""{outputVeideoPath}""";
using (Process process = Process.Start(@".\ffmpeg\ffmpeg.exe", arg))
{
process.WaitForExit();
}
});
}
/// <summary>
/// Clear Folder
/// </summary>
/// <param name="path">삭제할 경로</param>
public static void ClearFolder(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
// remove all files
foreach (FileInfo fi in dir.GetFiles())
fi.Delete();
// remove dir recursive
foreach (DirectoryInfo di in dir.GetDirectories())
{
ClearFolder(di.FullName);
di.Delete();
}
}
반응형
'Frontend > WPF' 카테고리의 다른 글
[WPF] Grid를 Bitmap 이미지로 변환 후 저장하기 (0) | 2023.04.08 |
---|---|
WPF에서 Windows Forms(WinForm) Control 사용하기 (0) | 2023.02.23 |
[WPF] 이미지 자르기 (1) | 2022.10.03 |
[WPF] 이미지 불러오기 (0) | 2022.10.03 |
[Devexpress] GridControl 자동 번호 매기기 (0) | 2022.10.03 |
@고지니어스 :: 규니의 개발 블로그
IT 기술과 개발 내용을 포스팅하는 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!