实例介绍
为便于说明,均采用后台代码。
使用的ffmpeg为最2025.12.22版本,请尽量不要使用其他版本。在Demo里面的App文件夹内。
将MediaLibrary编译为Dll,在你的项目中添加引用就可以,全部源码,可自行修改。
包括:取得音频图像、取得视频图像、删除视频片段、 删除音频片段、视频添加图像、叠加视频、叠加音频、插入视频、图像生成视频、视频调色、添加文字、合并视频、视频旋转等一些常用功能,全部功能均可分段或多段同时操作,带有进度。有函数说明和Demo。
由于是异步操作,有的功能点了按钮会反应慢一点,不要连续点击。
简单的功能比如转码、改分辨率等就不写在函数里面了,自行添加。这里的函数全部支持分段操作,语句复杂度较高,如有错误自行修正。
绿幕、滤镜等操作,由于是一个相当繁琐复杂的操作,这里就不写了,下一期再介绍。

using System.Windows;
using System.Windows.Media.Imaging;
using MediaLibrary.Actions;
using MediaLibrary.Functions;
using static MediaLibrary.Functions.Configuration;
namespace FFmpeg_Demo
{
/// <summary>
/// 文件"Back_Audio.mp3"必须保留,可以换成其他mp3文件,名称必须为"Back_Audio.mp3",其他mp4、图像文件可根据需要自行设置,
/// 测试文件:input.mp4,01.png,02.png,03.png,Lt.ttf(字体) 可自行指定路径和文件名。
/// 输出文件为output.mp4,为临时生成文件,自动写入覆盖,完成一个项目后自行另存。
///
/// 注意:中文文件名在程序里需加上双引号(""),如果我疏忽了,自行添加,否则不能正常导出视频
/// </summary>
public partial class MainWindow : Window
{
private readonly Progress<double[]> progress;
private readonly string VideoFile = "input.mp4";
public MainWindow()
{
InitializeComponent();
MediaLibrary.Functions.VideoInfo.GetVideoInfo(VideoFile);
progress = new Progress<double[]>(value =>
{
Dispatcher.Invoke(() =>
{
string p = "当前(视频处理的时间或帧数):" value[0] ". ---- 进度:" value[1].ToString("0.00") " %";
Label_Progress.Content = p;
});
});
}
/// <summary>
/// 取得音频图像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Button_Click(object sender, RoutedEventArgs e)
{
Wave_Image.Source = await MediaLibrary.Actions.ExtractionWaveImage.ToImage(VideoFile, (int)Wave_Image.Width, (int)Wave_Image.Height, "green");
}
/// <summary>
/// 取得视频图像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
// 取得 从3秒开始,长度51秒 的全部帧图像
List<BitmapSource> extractedFrames = await ExtractionFrames.ToImage(ExtractionFrames.ImageMode.Timefragment, VideoFile, progress, 3, 51);
// 取得全部图像
//List<BitmapSource> extractedFrames = await ExtractionFrames.ToImage(ExtractionFrames.ImageMode.All, VideoFile, progress);
// 取得每秒第一帧图像
//List<BitmapSource> extractedFrames = await ExtractionFrames.ToImage(ExtractionFrames.ImageMode.Everysecond, VideoFile, progress);
Extraction_Image.Source = extractedFrames[0]; // 显示第一幅
MessageBox.Show("共有图像:" extractedFrames.Count);
}
/// <summary>
/// 删除视频片段
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时删除2段视频,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 删除0秒至12秒
// 第一条须注明 生成文件大小、生成质量、音频质量,如不注明,则使用默认设置
Configuration.Project pr = new()
{
Etype = Configuration.EditType.DeleteVideo, // 操作类型
Compression = Configuration.compression.Default, // 生成文件大小 可选填
Crf = Configuration.crf.Medium, // 生成质量 可选填
Audioquality = Configuration.audioquality.Default, // 音频质量 可选填
Begin_Time = 0, // 开始时间
End_Time = 12, // 结束时间
};
Configuration.projects.Add(pr);
// 删除40秒至43秒
// 第一条注明了,后面就不需注明
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.DeleteVideo,
Begin_Time = 40,
End_Time = 43,
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, EditType.DeleteVideo, progress);
}
/// <summary>
/// 删除音频片段
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_3(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时删除2段音频,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 删除后视频、音频保持原样,不做设置
// 删除0-12秒音频
Configuration.Project pr = new()
{
Etype = Configuration.EditType.DeleteAudio, // 操作类型
Begin_Time = 0, // 开始时间
End_Time = 12, // 结束时间
};
Configuration.projects.Add(pr);
// 删除40-43秒音频
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.DeleteAudio,
Begin_Time = 40,
End_Time = 43,
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, EditType.DeleteAudio, progress);
}
/// <summary>
/// 视频添加图像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_4(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时添加3幅图像,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 视频5秒至15秒添加一幅图像
// 第一条须注明 生成文件大小、生成质量、音频质量,如不注明,则使用默认设置
// 第一条注明了,后面就不需注明
Configuration.Project pr = new()
{
Etype = Configuration.EditType.AddImage, // 操作类型
Compression = Configuration.compression.SLow, // 生成文件大小 可选填
Crf = Configuration.crf.SHeight, // 生成质量 可选填
Audioquality = Configuration.audioquality.FourK, // 音频质量 可选填
Begin_Time = 5, // 开始时间
End_Time = 15, // 结束时间
OffsetX = 10, // 位置 x
OffsetY = 20, // 位置 y
MediPath = "01.png"
};
Configuration.projects.Add(pr);
// 视频10秒至20秒添加一幅图像
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.AddImage,
Begin_Time = 20,
End_Time = 25,
OffsetX = 10,
OffsetY = 20,
MediPath = "02.png"
};
Configuration.projects.Add(pr1);
// 视频35秒至45秒添加一幅图像
Configuration.Project pr2 = new()
{
Etype = Configuration.EditType.AddImage,
Begin_Time = 35,
End_Time = 45,
OffsetX = 10,
OffsetY = 20,
MediPath = "03.png"
};
Configuration.projects.Add(pr2);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.AddImage, progress);
}
/// <summary>
/// 叠加视频
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_5(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时添加3个视频,按添加时长自动循环,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 生成后视频、音频保持原样,不做设置
// 0-10秒插入视频
Configuration.Project pr = new()
{
Etype = Configuration.EditType.AddVideo, // 操作类型
Begin_Time = 0, // 开始时间
End_Time = 10, // 结束时间
OffsetX = 10, // 位置 x
OffsetY = 20, // 位置 y
ScaleWidth = 200, // 宽度
ScaleHeight = 200, // 高度
MediPath = "overlay1.mp4"
};
Configuration.projects.Add(pr);
// 20-31秒插入视频
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.AddVideo,
Begin_Time = 20,
End_Time = 31,
OffsetX = 21,
OffsetY = 30,
ScaleWidth = 200,
ScaleHeight = 200,
MediPath = "overlay2.mp4"
};
Configuration.projects.Add(pr1);
// 40-50秒插入视频
Configuration.Project pr2 = new()
{
Etype = Configuration.EditType.AddVideo,
Begin_Time = 40,
End_Time = 50,
OffsetX = 42,
OffsetY = 52,
ScaleWidth = 200,
ScaleHeight = 200,
MediPath = "overlay3.mp4"
};
Configuration.projects.Add(pr2);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.AddVideo, progress);
}
/// <summary>
/// 叠加音频
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_6(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时添加2个音频,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 第一条须注明 音频质量,如不注明,则使用默认设置
// 5-20秒加入音频
Configuration.Project pr = new()
{
Etype = Configuration.EditType.AddAudio, // 操作类型
Audioquality = audioquality.FourK, // 音频质量 可选填
Begin_Time = 5, // 开始时间
End_Time = 20, // 结束时间
MediPath = "Back_Audio.mp3",
Volume = 0.5 // 音量
};
Configuration.projects.Add(pr);
// 25-40秒加入音频
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.AddAudio,
Begin_Time = 25,
End_Time = 40,
MediPath = "Back_Audio.mp3",
Volume = 1
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.AddAudio, progress);
}
/// <summary>
/// 插入视频
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_7(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时插入2个视频,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 第一条须注明 音频质量,如不注明,则使用默认设置
// 10秒处插入视频
Configuration.Project pr = new()
{
Etype = Configuration.EditType.InsertVideo, // 操作类型
Audioquality = audioquality.Default, // 音频质量 可选填
Begin_Time = 10, // 插入时间点
MediPath = "overlay1.mp4"
};
Configuration.projects.Add(pr);
// 25秒处插入视频
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.InsertVideo,
Begin_Time = 25,
MediPath = "overlay3.mp4"
};
Configuration.projects.Add(pr1);
// 视频长度为:所有插入的长度 视频本来长度
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.InsertVideo, progress);
}
/// <summary>
/// 图像生成视频
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_8(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时3幅图像生成视频,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
/*
* 注意:
* 图像大小与设定的视频大小必须一致!!!!!!!
* 背景音乐长度必须大于生成视频的长度,这里文件为"Back_Audio.mp3",长度3分钟,生成长度不要超过!。
*/
// 视频5秒至15秒添加一幅图像
// 第一条须注明 必须设置宽度高度!, 生成文件大小、生成质量、音频质量,如不注明,则使用默认设置
// 第一条注明了,后面就不需注明
Configuration.Project pr = new()
{
Etype = Configuration.EditType.ImageToVideo, // 操作类型
Crf = crf.Default, // 生成质量 可选填
Audioquality = audioquality.Default, // 音频质量 可选填
MediPath = "01.png",
ScaleWidth = 1920, // 宽度
ScaleHeight = 1080, // 高度
Transition = Configuration.XFades[(int)Configuration.XFade.Fade], // 切换特效 共57 种
Duration = 9, // 时长
XfadeDuration = 1, // 特效切换时长
};
Configuration.projects.Add(pr);
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.ImageToVideo,
MediPath = "02.png",
Transition = Configuration.XFades[(int)Configuration.XFade.Circleclose], // 切换特效 共57 种
Duration = 12,
XfadeDuration = 1,
};
Configuration.projects.Add(pr1);
// 最后一段可以不填 XfadeDuration长度和特效
Configuration.Project pr2 = new()
{
Etype = Configuration.EditType.ImageToVideo,
MediPath = "03.png",
Duration = 13,
};
Configuration.projects.Add(pr2);
// 总时长应为34秒,但是特效切换时间需扣除,所以生成视频为32秒
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(null, Configuration.EditType.ImageToVideo, progress);
}
/// <summary>
/// 视频调色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_9(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时2个片段调整为黑白(颜色可自定),可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 5-15秒调整为黑白(颜色可以不填,默认为黑白色)
// 第一条须注明 生成文件大小、生成质量,如不注明,则使用默认设置
// 第一条注明了,后面就不需注明
Configuration.Project pr = new()
{
Etype = Configuration.EditType.ColorAdjustment, // 操作类型
Crf = crf.Default, // 生成质量 可选填
Compression = compression.Default, // 生成文件大小 可选填
Begin_Time = 5, // 开始时间
End_Time = 15, // 结束时间
ColorRr = 0.299, // 红色-红
ColorRg = 0.587, // 红色-绿
ColorRb = 0.114, // 红色-蓝
ColorGr = 0.299, // 绿色-红
ColorGg = 0.587, // 绿色-绿
ColorGb = 0.114, // 绿色-蓝
ColorBr = 0.299, // 蓝色-红
ColorBg = 0.587, // 蓝色-绿
ColorBb = 0.114, // 蓝色-蓝
};
Configuration.projects.Add(pr);
// 25-30秒调整为黑白
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.ColorAdjustment,
Begin_Time = 25,
End_Time = 30,
ColorRr = 0.299,
ColorRg = 0.587,
ColorRb = 0.114,
ColorGr = 0.299,
ColorGg = 0.587,
ColorGb = 0.114,
ColorBr = 0.299,
ColorBg = 0.587,
ColorBb = 0.114,
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.ColorAdjustment, progress);
}
/// <summary>
/// 添加文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_10(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 同时2个片段添加文字,可以持续添加,时间段不要重复,函数本身不做校验,自行控制
// 第一条须注明 生成文件大小、生成质量,如不注明,则使用默认设置
// 5-15秒,400、600坐标添加文字
Configuration.Project pr = new()
{
Etype = Configuration.EditType.WriteText, // 操作类型
Compression = compression.Default, // 生成文件大小 可选填
Crf = crf.Default, // 生成质量 可选填
Begin_Time = 5, // 开始时间
End_Time = 15, // 结束时间
OffsetX = 400, // 位置 x
OffsetY = 600, // 位置 y
Text = "锦瑟无端五十弦", // 文字内容
TextFont = "lt.ttf", // 字体文件
TextFontsize = 50, // 文字大小
TextColor = "red", // 文字颜色
TextTransparency = 1, // 文字透明度
TextShadowcolor = "black", // 文字颜色
TextShadowTransparencyr = 1, // 阴影透明度
TextShadowX = 5, // 阴影偏移 x
TextShadowY = 5, // 阴影偏移 y
};
Configuration.projects.Add(pr);
// 20-30秒,400、600坐标添加文字
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.WriteText,
Begin_Time = 20,
End_Time = 30,
OffsetX = 400,
OffsetY = 600,
Text = "一弦一柱思华年",
TextFont = "lt.ttf",
TextFontsize = 50,
TextColor = "white",
TextTransparency = 0.9,
TextShadowcolor = "black",
TextShadowTransparencyr = 0.9,
TextShadowX = 5,
TextShadowY = 5,
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.WriteText, progress);
}
/// <summary>
/// 合并视频
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_11(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 2个视频合并,可以持续添加
// 第一条须注明 生成文件大小、音频质量,如不注明,则使用默认设置
// 第1个
Configuration.Project pr = new()
{
Etype = Configuration.EditType.VideoMerging, // 操作类型
Crf = crf.Default, // 生成质量 可选填
Audioquality = audioquality.Default, // 音频质量 可选填
MediPath = "overlay1.mp4",
ScaleWidth = 1280, // 宽度
ScaleHeight = 720, // 高度
};
Configuration.projects.Add(pr);
// 第2个
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.VideoMerging,
MediPath = "input.mp4",
};
Configuration.projects.Add(pr1);
// 第3个
Configuration.Project pr2 = new()
{
Etype = Configuration.EditType.VideoMerging,
MediPath = "overlay2.mp4",
};
Configuration.projects.Add(pr2);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(null, Configuration.EditType.VideoMerging, progress);
}
/// <summary>
/// 视频旋转
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Click_12(object sender, RoutedEventArgs e)
{
Configuration.projects.Clear();
// 第一条须注明 生成文件大小、音频质量,如不注明,则使用默认设置
// 5-10秒 顺时针旋转10度
Configuration.Project pr = new()
{
Etype = Configuration.EditType.Rotation, // 操作类型
Compression = compression.Default, // 生成文件大小 可选填
Audioquality = audioquality.Default, // 音频质量 可选填
Begin_Time = 5, // 开始时间
End_Time = 15, // 结束时间
RotationAngle = 10, // 旋转角度
};
Configuration.projects.Add(pr);
// 25-30秒 顺时针旋转50度
Configuration.Project pr1 = new()
{
Etype = Configuration.EditType.Rotation,
Begin_Time = 25,
End_Time = 30,
RotationAngle = 50,
};
Configuration.projects.Add(pr1);
// 输出文件自动为当前文件夹下面的 "output.mp4"
Fragments.Option(VideoFile, Configuration.EditType.Rotation, progress);
}
}
}
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论