Another Simple C# Wrapper For FFmpeg
17. May 2010 10:54After reading below article do not forget to checkout Important Update to Another Simple C# Wrapper For FFmpeg
When you want to encode uploaded videos to your website you are in luck if you use PHP, encoding uploaded videos to your web site on the fly quite easy on Linux based servers. Install FFmpeg and get a PHP wrapper for FFmpeg and you are good to go.
Story is a little bit different on Windows servers. There is no support from .Net framework; although there are couple of open source C# .Net wrappers for FFmpeg that encodes video on the fly, they are mostly incomplete. There are also commercial ones such as Mediahandler are not free/open-source.
In short, I couldn't get what i wanted from open-source ones so I've decided to write my own C# wrapper for FFmpeg.
My .Net skills are no where near good but here what i ended up with.
See usage in the example at the bottom of this post. Download whole project VideoEncoder.rar (48.54 kb) or download changes made by Anders (see comments) VideoEncoderAsync.rar (6.79 kb)
Don't forget to download FFmpeg win32 build and put in to FFmpeg folder in the project
My solution has 5 classes;
Encoder.cs, does the main job and gets FFmpegPath as input.
It has 3 methods :
- EncodeVideo: Encodes video with FFmpeg according to commands
- GetVideoThumbnail: Gets video thumbnail image without encoding video
- GetVideoInfo: Gets information about source video and assigns it to VideoFile class such as Duration, BitRate, AudioFormat, VideoFormat, Height, Width
To do: Implement a class to insert logo on to the video with ffmpeg -vhook
Source of Encoder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
using
System;
using
System.Diagnostics;
using
System.IO;
using
System.Text.RegularExpressions;
namespace
VideoEncoder
{
public
class
Encoder
{
public
EncodedVideo EncodeVideo(VideoFile input,
string
encodingCommand,
string
outputFile,
bool
getVideoThumbnail)
{
EncodedVideo encoded =
new
EncodedVideo();
Params =
string
.Format(
"-i {0} {1} {2}"
, input.Path, encodingCommand, outputFile);
string
output = RunProcess(Params);
encoded.EncodingLog = output;
encoded.EncodedVideoPath = outputFile;
if
(File.Exists(outputFile))
{
encoded.Success =
true
;
//get thumbnail?
if
(getVideoThumbnail)
{
string
saveThumbnailTo = outputFile +
"_thumb.jpg"
;
if
(GetVideoThumbnail(input, saveThumbnailTo))
{
encoded.ThumbnailPath = saveThumbnailTo;
}
}
}
else
{
encoded.Success =
false
;
}
return
encoded;
}
public
bool
GetVideoThumbnail(VideoFile input,
string
saveThumbnailTo)
{
if
(!input.infoGathered)
{
GetVideoInfo(input);
}
int
secs;
//divide the duration in 3 to get a preview image in the middle of the clip
//instead of a black image from the beginning.
secs = (
int
)Math.Round(TimeSpan.FromTicks(input.Duration.Ticks / 3).TotalSeconds, 0);
string
Params =
string
.Format(
"-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo"
, input.Path, saveThumbnailTo, secs);
string
output = RunProcess(Params);
if
(File.Exists(saveThumbnailTo))
{
return
true
;
}
else
{
//try running again at frame 1 to get something
Params =
string
.Format(
"-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo"
, input.Path, saveThumbnailTo, 1);
output = RunProcess(Params);
if
(File.Exists(saveThumbnailTo))
{
return
true
;
}
else
{
return
false
;
}
}
}
public
void
GetVideoInfo(VideoFile input)
{
string
Params =
string
.Format(
"-i {0}"
, input.Path);
string
output = RunProcess(Params);
input.RawInfo = output;
input.Duration = ExtractDuration(input.RawInfo);
input.BitRate = ExtractBitrate(input.RawInfo);
input.RawAudioFormat = ExtractRawAudioFormat(input.RawInfo);
input.AudioFormat = ExtractAudioFormat(input.RawAudioFormat);
input.RawVideoFormat = ExtractRawVideoFormat(input.RawInfo);
input.VideoFormat = ExtractVideoFormat(input.RawVideoFormat);
input.Width = ExtractVideoWidth(input.RawInfo);
input.Height = ExtractVideoHeight(input.RawInfo);
input.infoGathered =
true
;
}
private
string
RunProcess(
string
Parameters)
{
//create a process info
ProcessStartInfo oInfo =
new
ProcessStartInfo(
this
.FFmpegPath, Parameters);
oInfo.UseShellExecute =
false
;
oInfo.CreateNoWindow =
true
;
oInfo.RedirectStandardOutput =
true
;
oInfo.RedirectStandardError =
true
;
//Create the output and streamreader to get the output
string
output =
null
; StreamReader srOutput =
null
;
//try the process
try
{
//run the process
Process proc = System.Diagnostics.Process.Start(oInfo);
proc.WaitForExit();
//get the output
srOutput = proc.StandardError;
//now put it in a string
output = srOutput.ReadToEnd();
proc.Close();
}
catch
(Exception)
{
output =
string
.Empty;
}
finally
{
//now, if we succeded, close out the streamreader
if
(srOutput !=
null
)
{
srOutput.Close();
srOutput.Dispose();
}
}
return
output;
}
public
string
FFmpegPath {
get
;
set
; }
private
string
Params {
get
;
set
; }
private
TimeSpan ExtractDuration(
string
rawInfo)
{
TimeSpan t =
new
TimeSpan(0);
Regex re =
new
Regex(
"[D|d]uration:.((\\d|:|\\.)*)"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
if
(m.Success)
{
string
duration = m.Groups[1].Value;
string
[] timepieces = duration.Split(
new
char
[] {
':'
,
'.'
});
if
(timepieces.Length == 4)
{
t =
new
TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3]));
}
}
return
t;
}
private
double
ExtractBitrate(
string
rawInfo)
{
Regex re =
new
Regex(
"[B|b]itrate:.((\\d|:)*)"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
double
kb = 0.0;
if
(m.Success)
{
Double.TryParse(m.Groups[1].Value,
out
kb);
}
return
kb;
}
private
string
ExtractRawAudioFormat(
string
rawInfo)
{
string
a =
string
.Empty;
Regex re =
new
Regex(
"[A|a]udio:.*"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
if
(m.Success)
{
a = m.Value;
}
return
a.Replace(
"Audio: "
,
""
);
}
private
string
ExtractAudioFormat(
string
rawAudioFormat)
{
string
[] parts = rawAudioFormat.Split(
new
string
[] {
", "
}, StringSplitOptions.None);
return
parts[0].Replace(
"Audio: "
,
""
);
}
private
string
ExtractRawVideoFormat(
string
rawInfo)
{
string
v =
string
.Empty;
Regex re =
new
Regex(
"[V|v]ideo:.*"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
if
(m.Success)
{
v = m.Value;
}
return
v.Replace(
"Video: "
,
""
); ;
}
private
string
ExtractVideoFormat(
string
rawVideoFormat)
{
string
[] parts = rawVideoFormat.Split(
new
string
[] {
", "
}, StringSplitOptions.None);
return
parts[0].Replace(
"Video: "
,
""
);
}
private
int
ExtractVideoWidth(
string
rawInfo)
{
int
width = 0;
Regex re =
new
Regex(
"(\\d{2,4})x(\\d{2,4})"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
if
(m.Success)
{
int
.TryParse(m.Groups[1].Value,
out
width);
}
return
width;
}
private
int
ExtractVideoHeight(
string
rawInfo)
{
int
height = 0;
Regex re =
new
Regex(
"(\\d{2,4})x(\\d{2,4})"
, RegexOptions.Compiled);
Match m = re.Match(rawInfo);
if
(m.Success)
{
int
.TryParse(m.Groups[2].Value,
out
height);
}
return
height;
}
}
}
|
EncodedVideo.cs is output package for Encode method
Source of EncodedVideo.cs
1
2
3
4
5
6
7
8
9
10
11
|
namespace
VideoEncoder
{
public
class
EncodedVideo
{
public
string
EncodedVideoPath {
get
;
set
; }
public
string
ThumbnailPath {
get
;
set
; }
public
string
EncodingLog {
get
;
set
; }
public
bool
Success {
get
;
set
; }
}
}
|
VideoFile.cs holds properties of input/source video
Source of VideoFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
using
System;
using
System.IO;
namespace
VideoEncoder
{
public
class
VideoFile
{
private
string
_Path;
public
string
Path
{
get
{
return
_Path;
}
set
{
_Path = value;
}
}
public
TimeSpan Duration {
get
;
set
; }
public
double
BitRate {
get
;
set
; }
public
string
RawAudioFormat {
get
;
set
; }
public
string
AudioFormat {
get
;
set
; }
public
string
RawVideoFormat {
get
;
set
; }
public
string
VideoFormat {
get
;
set
; }
public
int
Height {
get
;
set
; }
public
int
Width {
get
;
set
; }
public
string
RawInfo {
get
;
set
; }
public
bool
infoGathered {
get
;
set
; }
public
VideoFile(
string
path)
{
_Path = path;
Initialize();
}
private
void
Initialize()
{
this
.infoGathered =
false
;
if
(
string
.IsNullOrEmpty(_Path))
{
throw
new
Exception(
"Video file Path not set or empty."
);
}
if
(!File.Exists(_Path))
{
throw
new
Exception(
"The video file "
+ _Path +
" does not exist."
);
}
}
}
}
|
Project also have two helper classes QuickAudioEncodingCommands.cs and QuickVideoEncodingCommands.cs to make video encoding easier. I simple created FFmpeg command-line snippets for easy encoding
Source of QuickAudioEncodingCommands.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
///
///
/// Ready made encoding commands for FFmpeg
/// Use when calling EncodeVideo commands as string encodingCommand
/// Add remove as you like
///
///
///
public
class
QuickAudioEncodingCommands
{
//mp3
public
static
string
MP3128Kbps =
"-y -ab 128k -ar 44100"
;
public
static
string
MP396Kbps =
"-y -ab 96k -ar 44100"
;
public
static
string
MP364Kbps =
"-y -ab 64k -ar 44100"
;
public
static
string
MP332Kbps =
"-y -ab 32k -ar 44100"
;
}
|
Source of QuickVideoEncodingCommands.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
///
///
/// Ready made encoding commands for FFmpeg
/// Use when calling EncodeVideo commands as string encodingCommand
/// Add remove as you like
///
///
///
namespace
VideoEncoder
{
public
class
QuickVideoEncodingCommands
{
//-b
static
string
LQVideoBitrate =
"256k"
;
static
string
MQVideoBitrate =
"512k"
;
static
string
HQVideoBitrate =
"756k"
;
static
string
VHQVideoBitrate =
"1024k"
;
//-ab
static
string
LQAudioBitrate =
"32k"
;
static
string
MQAudioBitrate =
"64k"
;
static
string
HQAudioBitrate =
"96k"
;
static
string
VHQAudioBitrate =
"128k"
;
//-ar
static
string
LQAudioSamplingFrequency =
"22050"
;
static
string
MQAudioSamplingFrequency =
"44100"
;
static
string
HQAudioSamplingFrequency =
"44100"
;
//-s
static
string
SQCIF =
"sqcif"
;
//128x96
static
string
QCIF =
"qcif"
;
//176x144
static
string
QVGA =
"qvga"
;
//320x240
static
string
CIF =
"cif"
;
//352x288
static
string
VGA =
"vga"
;
//640x480
static
string
SVGA =
"svga"
;
//800x600
// todo
//insert logo
//
//string LogoPath ="/Path/to/transparent/png";
//string PositionX ="0";
//string PositionY ="0";
//string.Format("-vhook \"vhook/imlib2.dll -x {0} -y {1} -i {2}\"", PositionX,PositionY,LogoPath);
//flv
public
static
string
FLVLowQualityQCIF =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f flv"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
FLVMediumQualityCIF =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f flv"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
FLVHighQualityVGA =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f flv"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
public
static
string
FLVVeryHighQualitySVGA =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f flv"
, VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);
public
static
string
FLVLowQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f flv"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
FLVMediumQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f flv"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
FLVHighQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f flv"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
public
static
string
FLVVeryHighQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f flv"
, VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);
//3gp
public
static
string
THREEGPLowQualitySQCIF =
string
.Format(
"-y -acodec aac -ac 1 -b {0} -ab {1} -ar {2} -s {3} -f 3gp"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, SQCIF);
public
static
string
THREEGPMediumQualityQCIF =
string
.Format(
"-y -acodec aac -b {0} -ab {1} -ar {2} -s {3} -f 3gp"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, QCIF);
public
static
string
THREEGPHighQualityCIF =
string
.Format(
"-y -acodec aac -b {0} -ab {1} -ar {2} -s {3} -f 3gp"
, VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, CIF);
//mp4
public
static
string
MP4LowQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f mp4"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
MP4MediumQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f mp4"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
MP4HighQualityKeepOriginalSize =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -f mp4"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
public
static
string
MP4LowQualityQVGA =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f mp4"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
MP4MediumQualityCIF =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f mp4"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
MP4HighQualityVGA =
string
.Format(
"-y -b {0} -ab {1} -ar {2} -s {3} -f mp4"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
//WMV
public
static
string
WMVLowQualityQVGA =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
WMVMediumQualityCIF =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
WMVHighQualityVGA =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
public
static
string
WMVVeryHighQualitySVGA =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}"
, VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);
public
static
string
WMVLowQualityKeepOriginalSize =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2}"
, LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
public
static
string
WMVMediumQualityKeepOriginalSize =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2}"
, MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
public
static
string
WMVHighQualityKeepOriginalSize =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2}"
, HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
public
static
string
WMVVeryHighQualityKeepOriginalSize =
string
.Format(
"-y -vcodec wmv2 -acodec wmav2 -b {0} -ab {1} -ar {2}"
, VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
using
System;
using
VideoEncoder;
public
partial
class
_Default : System.Web.UI.Page
{
protected
void
Page_Load(
object
sender, EventArgs e)
{
Encoder enc =
new
Encoder();
enc.FFmpegPath = Server.MapPath(
"~/FFmpeg/ffmpeg.exe"
);
VideoFile inputv =
new
VideoFile(Server.MapPath(
"~/WorkingFolder/SourceVideo.wmv"
));
string
outputVPath = Server.MapPath(
"~/WorkingFolder/OutputVideo.flv"
);
string
saveThumbnailTo = Server.MapPath(
"~/WorkingFolder/OutputVideoThumbnail.jpg"
);
// to get video thumbnail call
enc.GetVideoThumbnail(inputv,saveThumbnailTo);
// to encode video call
EncodedVideo encoded = enc.EncodeVideo(inputv, QuickVideoEncodingCommands.FLVVeryHighQualityKeepOriginalSize, outputVPath,
true
);
if
(encoded.Success)
{
Response.Write(encoded.ThumbnailPath);
Response.Write(
"<br>"
);
Response.Write(encoded.EncodedVideoPath);
Response.Write(
"<br>"
);
Response.Write(encoded.EncodingLog);
}
else
{
Response.Write(encoded.EncodingLog);
}
}
}
|
This project borrowed some code from http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/
Quite a huge source thanks.
You make me wanna change mind over to .net c#
Great article! Thanks!
Hei, thank you very much for this code
I have fixed a bug where filenames with spaces caused errors and and added Async methods, progress event and finished event. Will be adding some more functionality soon. Drop me a line if ur interested.
Best regards, Anders.
Anders, have you posted your code somewhere?
Hi, not yet. I need to add more error handling, do some more testing and clean up the code. I will ping here when it's ready
Thanks!
i'd love to post it here once it is available if you don't mind
Sure, I think it's stable enough now. Atleast it's good enough for the use I intended
I haven't tested this in anything but WinForms as that is what i need if for.
Here's a download link for the source:
www.mediafire.com/.../VideoEncoderAsync.rar
Changelog:
-Fixed filename with spaces bug
-Fixed deadlock issue with process execution
-Added delegates, events and methods for progress and finish
-Added extra fields in VideoFile for video and audio bitrate, framerate, totalframes
-Added extraction methods for the above
-Added RunProcessAsync
-Added EncodeVideoAsync and EncodeVideoAsyncAutoCommand
-Added encoder threads *read below*
Threads:
Threads in ffmpeg is not straight forward. Some codecs dont support multiple threads. The maximum thread count is not the same for codecs.
Auto thread count can be used passing 0 as parameter, not all codecs support auto thead count.
To disable threads, pass 1 as parameter.
Example usage in WinForms: Add methods Progress and Finish
Encoder enc = new Encoder();
enc.FFmpegPath = "ffmpeg.exe";
VideoFile videoFile = new VideoFile("C:\\some file.avi");
string outputFile = "C:\\output file.wmv";
enc.OnEncodeProgress += new EncodeProgressEventHandler(Progress);
enc.OnEncodeFinished += new EncodeFinishedEventHandler(Finished);
enc.EncodeVideoAsync(videoFile, QuickVideoEncodingCommands.WMVVeryHighQualityKeepOriginalSize, outputFile, this, 1);
Enjoy
Best regards, Anders Tornes
Oh, also, here's a link to an FFmpeg automated builds archive. Great for getting the latest binaries
http://ffmpeg.arrozcru.org/autobuilds/
//AT
Hi,
I have the progressevent working firing in a WPF application c#
No input is being received so i am not getting the total frames to drive the progressbar, is there something i am missing from your sample code to send in the data duration totalframes etc, if i put a value of frames progressbar works your code //Set total frames
epe.TotalFrames = tempVideoFile.TotalFrames;
the tempVideoFile is not getting the TotalFrames.
Tommy
Hi,
Ok got it, i was using the RunProcessLargefiles for ASpnet which was causing the problem(regarding my last message to you Progressbar) Changed back to RunProgress all working as should thanks
Encoder enc2 = new Encoder();
string inputfile = _ctlUploadFile.Text;
VideoFile videoFile2 = new VideoFile(inputfile);
enc2.FFmpegPath = "C:\\Test/ffmpeg/ffmpeg.exe";
string outputFile2 = "C:\\Test/outputfile.mp4";
enc2.OnEncodeProgress += new EncodeProgressEventHandler(ProgressStart);
enc2.OnEncodeFinished += new EncodeFinishedEventHandler(Finished);
string saveThumbnailTo = "C:\\Test/OutputVideoThumbnail.jpg";
enc2.GetVideoThumbnail(videoFile2, saveThumbnailTo);
enc2.EncodeVideoAsync(videoFile2, QuickVideoEncodingCommands.MP4HighQualityKeepOriginalSize,outputFile2, 1);
For those c# WPF code progressbar
private void ProgressStart(object sender,EncodeProgressEventArgs e)
{
pb.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new DispatcherOperationCallback(delegate
{
// ignore just teting _ctlFileTransferLabel.Text =" % * " + e.Percentage+ " Total Frames *" + e.TotalFrames + " RawData *// " + e.RawOutputLine;
// pb.Minimum = 0;
// pb.Maximum = 100;
pb.Value = e.Percentage;// pb is the progressbar
return null;
}), null);
}
Tommy
How can I use progress bar in my winform ? I use your change code, but have error in ProgressStart and Finish. please help me! my progressbar name is pb.
Hi,
Final thing on progress for correct percentage to work
public void GetVideoInfo(VideoFile input)
{
string Params = string.Format("-i \"{0}\"", input.Path);
string output = RunProcess(Params);
input.RawInfo = output;
input.Duration = ExtractDuration(input.RawInfo);
input.BitRate = ExtractBitrate(input.RawInfo);
input.RawAudioFormat = ExtractRawAudioFormat(input.RawInfo);
input.AudioFormat = ExtractAudioFormat(input.RawAudioFormat);
input.RawVideoFormat = ExtractRawVideoFormat(input.RawInfo);
input.VideoFormat = ExtractVideoFormat(input.RawVideoFormat);
input.Width = ExtractVideoWidth(input.RawInfo);
input.Height = ExtractVideoHeight(input.RawInfo);
input.FrameRate = ExtractFrameRate(input.RawVideoFormat);
input.TotalFrames = ExtractTotalFrames(input.Duration, input.FrameRate / 100);// /100 needed here for correct percentage
input.AudioBitRate = ExtractAudioBitRate(input.RawAudioFormat);
input.VideoBitRate = ExtractVideoBitRate(input.RawVideoFormat);
input.infoGathered = true;
}
/100 needed input.Framerate or you can to the maths somewhere else
Tommy
I was trying to get to the latest code Anders posted, but the link doesn’t work. I'm hoping mediafire is just down right now?
Thanks for your work!
I have uploaded Anders' changes next to my download link
Need help
Hi, I have tried your c# wrapper for ffmpeg the output file is always empty 0kb, the encodingLog field is empty. I am using the latest built of ffmpeg version 0.6. The output did create the thumbl pic.
sample code:
MediaVerse.Converter.Encoder enc = new MediaVerse.Converter.Encoder();
enc.FFmpegPath = @"C:\Video\ffmpeg.exe";
string inputFile = @"C:\Video\Wall.avi";
VideoFile videoFile = new VideoFile(inputFile);
string outputFile = @"C:\Encoded\Wall.mp4";
EncodedVideo encodedVideo = enc.EncodeVideo(videoFile, QuickVideoEncodingCommands.MP4LowQualityQVGA, outputFile, true);
Need Help
the output file size is 0kb, the thumb pic file was created.
I am using ffmpeg version 0.6, same thing with version 0.5
MediaVerse.Converter.Encoder enc = new MediaVerse.Converter.Encoder();
enc.FFmpegPath = @"C:\Video\ffmpeg.exe";
string inputFile = @"C:\Video\Wall.avi";
VideoFile videoFile = new VideoFile(inputFile);
string outputFile = @"C:\Encoded\Wall.mp4";
EncodedVideo encodedVideo = enc.EncodeVideo(videoFile, QuickVideoEncodingCommands.MP4LowQualityQVGA, outputFile, true);
what does command line encoding returns? Try running ffmpeg on command line first to see if there is an error.
Hello,
thanks for such a nice wrapper .I want to add images in video file at bottom of video like youtube now a days.
please help what i have to do with wrapper .
please please help me.
This is what i use to insert logo
encodingCommand = "-y -vhook \"vhook/imlib2.dll -x 0 -y 0 -i " + LogoPath + "\" -acodec libfaac -ac 1 -ar 11025 -ab 12kb -b " + _SourceBitrate.ToString() + "k -f " + vidoeFormat;
You need to download ffmpeg with vhook from http://ffmpeg.arrozcru.org/builds/
hello nolovelust
sorry but i am newbie to this type development can u explain more like i what i have to do first ,
i mean i have to downloaded build from provided link now i have to install it or any thing ?please explain step to pre-requirement steps.
2.I found something in QuickVideoEncodingCommands.cs file insert logo which is commented and if i comment out it give syntax error...please give me example if u can
help me please
hello i have following output when i look into this variable
b Params = string.Format("-i {0} {1} {2}", input.Path, encodingCommand, outputFile);
string output = RunProcess(Params);
output=FFmpeg version SVN-r25512, Copyright (c) 2000-2010 the FFmpeg developers
built on Oct 18 2010 04:06:45 with gcc 4.4.2
configuration: --enable-gpl --enable-version3 --enable-libgsm --enable-pthreads --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libmp3lame --enable-libopenjpeg --enable-libschroedinger --enable-libopencore_amrwb --enable-libopencore_amrnb --enable-libvpx --arch=x86 --enable-runtime-cpudetect --enable-libxvid --enable-libx264 --extra-libs='-lx264 -lpthread' --enable-librtmp --extra-libs='-lrtmp -lpolarssl -lws2_32 -lwinmm' --target-os=mingw32 --enable-avisynth --cross-prefix=i686-mingw32- --cc='ccache i686-mingw32-gcc' --enable-memalign-hack
libavutil 50.32. 3 / 50.32. 3
libavcore 0. 9. 1 / 0. 9. 1
libavcodec 52.92. 0 / 52.92. 0
libavformat 52.83. 0 / 52.83. 0
libavdevice 52. 2. 2 / 52. 2. 2
libavfilter 1.52. 0 / 1.52. 0
libswscale 0.12. 0 / 0.12. 0
[mov,mp4,m4a,3gp,3g2,mj2 @ 01cfe060] multiple edit list entries, a/v desync might occur, patch welcome
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'D:\Data\Project\Project\ProjectWatermark\ProjectWatermark\bin\Debug\Demo.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isom
encoder : mp4creator 1.6.1d
Duration: 00:01:02.88, start: 0.000000, bitrate: 465 kb/s
Stream #0.0(eng): Video: mpeg4, yuv420p, 320x240 [PAR 1:1 DAR 4:3], 401 kb/s, 18 fps, 18 tbr, 90k tbn, 18 tbc
Stream #0.1(eng): Audio: aac, 22050 Hz, stereo, s16, 63 kb/s
Unrecognized option 'vhook'
this last line show that it doesnt work ..what should i do ?
please guys help me...any help would b appreciate...i dont know any other option i have tried lot to solve this or achieve this funcationality .
Some issue.
I tried to generate the thumbnail using your method on movie files in the range of 1MB to 2 Gigs.
On some the program just took minutes per video!
Also I couldn't get the thumbnails in other sizes as the original size.
So I changed the Params
Your code: string Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, secs);
into:
string Params = string.Format("-itsoffset -4 -i {0} -vcodec mjpeg -vframes 1 -an -f rawvideo -s 320x240 {1}", input.Path, saveThumbnailTo);
the 4 means take shot at 4 seconds, but of course can take it from anything else as well..
the -s which didn't work in the original params string now works.
So, in case others get these problems as well...
oh yeah, taking a thumbnail from a 2Gigs Video now takes only a second..
If you check the comment
"//divide the duration in 3 to get a preview image in the middle of the clip
//instead of a black image from the beginning.
"
you'll see that it ready whole file, for large files like 2GB, your approach is better.
hi..how can i set the height,width,bit ratio of the output video???
hello,
i am getting 0 as the duration of video. ffmpeg.exe process not starting yet .
please suggest ....
Can you post your source code?
hi..how can i set the height,width,bit ratio of the output video???
please give me a solution
@nolovelust solved. it was my fault . thanks .
a Suggestion :
In GetVideoThumbnail method we can change -f rawvideo (-f Force format option) into -f image2. It reduces the size of thumbnail file. Normally for a jpeg file (400x300) of size 800kb comes into 6kb.
Example :
Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, 1);
to
Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f image2", input.Path, saveThumbnailTo, 1);
Thanks.
hi i'm new to this.. can u please tell me step by step procedure, how to build this wrapper successfully.. please help me out with this..
thank you
//create a process info
ProcessStartInfo oInfo = new ProcessStartInfo(this.FFmpegPath, Parameters);
oInfo.UseShellExecute = false;
oInfo.CreateNoWindow = true;
oInfo.RedirectStandardOutput = true;
oInfo.RedirectStandardError = true;
//Create the output and streamreader to get the output
string output = null; StreamReader srOutput = null;
//try the process
try
{
//run the process
Process proc = System.Diagnostics.Process.Start(oInfo);
proc.WaitForExit();
//get the output
srOutput = proc.StandardError;
//now put it in a string
output = srOutput.ReadToEnd();
proc.Close();
}
This Error was copied from Jasons Blog. He also wrote this error.
Here's the fix:
//create a process info
ProcessStartInfo oInfo = new ProcessStartInfo(this.FFmpegPath, Parameters);
oInfo.UseShellExecute = false;
oInfo.CreateNoWindow = true;
oInfo.RedirectStandardOutput = true;
oInfo.RedirectStandardError = true;
//Create the output and streamreader to get the output
string output = "";
//try the process
try
{
//run the process
Process proc = new Process {StartInfo = oInfo};
proc.Start();
output = proc.StandardError.ReadToEnd();
proc.WaitForExit();
proc.Close();
}
catch (Exception)
{
output = string.Empty;
}
return output;
Comment: if you enable the redirectstandards. then ReadToEnd() has to be BEFORE The WaitForExit because
.net needs it..
if you try to get your readtoend() after the process exited.. well, hmm, not sure what you want to read there?
should be empty once the process exited..
Hi, this is great, thanks. I just getting one problem, when I am converting my mp4 into wmv or avi, it is not working, I think my command line have some missing, can anyone give me list of command line to convert mp4 to avi or mp4 to any other format.
Thanks,
hey, thank you very much for this article, but i have a problem, in the ExtractBitrate method always i got the m.Success false, anybody can help me please?
Hi All,
Anyone know how to add a watermark to the video when converting or even after converted ?
ps this has no loss in quality when converted
public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
Tommy
Ok i answered my own question about adding a watermark, so in this case i do not use the -vhook but the libvavfilter note: in my case i am using ffmpeg static 32bit build which has all needed built-in other than my preset though there are a few presets built-in. In your quickvideocommands.cs file add
public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
I just named it HD720x480 this will convert to hd size with no loss of quality picture and sound and output .mp4 so it is H.264 now this will not work if the logo png is not in the correct path, in the above it is in my bin debug folder so if your logo path is some where else add the correct path, the "" are needed as for movie=
so the watermark part of the above is -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" do not change the\" unless you know what you are doing and are doing it a different way. your logo will be placed in the top left hand corner, my png is transparent background and the size is 100x30 it can be any size you wish.
other options are
Top right corner
overlay=main_w-overlay_w-10:10 [out]"
Bottom left corner
overlay=10:main_h-overlay_h-10 [out]"
Bottom right corner
overlay=main_w-overlay_w-10:main_h-overlay_h-10 [out]"
Rember this adds the water mark during the conversion, doing it after the conversion will require alot more time to finish.
I hope i explained this easy, any problems just put your logo in the bin debug folder of your project and paste in the
public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
When you get it working you can try different logo path.
Best of luck!
Hi, I m facing File Deadlock issue, some process seems continue to run after completion which keeps the input file locked. Any help on that will be appreciated.
Hi thanks a lot for the article, i just have a problem now when i try converting to mpeg small files do convert but a file which is 25mb doesn't get converted it just stops at 2.59 mb which i don't understand why , do you have any idea why such a problem occurs ?