Merge image with a video with nreco - c#

I have converted an image in to a vedio using following code
NReco.VideoConverter.ConvertSettings setting = new NReco.VideoConverter.ConvertSettings();
setting.SetVideoFrameSize(FrameSizeWidth, FrameSizeHeight);
setting.VideoCodec = "libx264";
setting.AudioCodec = "mp3";
setting.CustomInputArgs = " -framerate 1/"+imageDuration;
setting.CustomOutputArgs = " -profile:v high -r 30";
FFMpegConv.ConvertMedia(inputFilePath, null, outputFIlePath, null, setting);
And also I have a mp4 video with me which is splited using the follwoing code.
var ffMpegConverter = new FFMpegConverter();
ffMpegConverter.ConvertMedia(SourceFile, Format.mp4, DestinationFile, Format.mp4,
new ConvertSettings()
{
Seek = StartTime,
MaxDuration = (EndTime-StartTime),
VideoCodec = "libx264",
AudioCodec = "mp3",
});
I need to concat these two videos. I used the fllowing code for it.Here the SourceVideoList array contains the two videos(Splite and image video)
var ffMpegConverter = new FFMpegConverter();
ffMpegConverter.ConcatMedia(SourceVideoList.ToArray(),OutputFile,null,new ConcatSettings());
But when i try to do it gives and error saying "Cannot find a matching stream for unlabeled input pad 3 on filter Parsed_concat_0".
Can some one help me on this

ConcatMedia method uses ffmpeg concat filter; it expects that all input video chunks have the same frame size and frame rate. In most cases error you faced (Cannot find a matching stream for unlabeled input pad 3 on filter Parsed_concat_0) means that video chunks have incompatible set of parameters. You can get more information by handling LogReceived event (to get ffmpeg console log output).
Note that you can use another ways to merge videos supported by ffmpeg (concat demuxer, concat protocol - see https://trac.ffmpeg.org/wiki/Concatenate for more details) with ConvertMedia method overload that accepts several input files.

Related

creating a video from frames

In my windows universal app, I'm trying to use a WinRT component: http://blogs.msdn.com/b/eternalcoding/archive/2013/03/06/developing-a-winrt-component-to-create-a-video-file-using-media-foundation.aspx (which is basically a C++ wrapper for sinkWriter)
to create a video with frames.
I put all this code in a C++ project and I can call it from my C# code without problem.
The problem come with the constructor first:
HRESULT CVideoGenerator::InitializeSinkWriter(Windows::Storage::Streams::IRandomAccessStream^ stream)
I'm not sure of how to create the stream:
var filename = "exportedVideo.wmv";
var folder = Windows.Storage.KnownFolders.VideosLibrary;
StorageFile storageFile = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
StorageFile file = await StorageFile.GetFileFromPathAsync(App.PhotoModel.Path);
CVideoGenerator videoGenerator = new CVideoGenerator(1280, 720, stream, 20);
The other thing is coming from this line:
hr = sinkWriter->SetInputMediaType(streamIndex, mediaTypeIn, NULL);
//hr 0xc00d5212 : No suitable transform was found to encode or decode the content. HRESULT
Any ideas ?
I've used this VideoGenerator sample, and got the same problem.
I'm not an expert of Media Foundation, but after some researchs, I've found that the problem was at these lines :
encodingFormat = MFVideoFormat_WMV3;
inputFormat = MFVideoFormat_RGB32;
Well, I've replaced the first format by the second one, like this :
encodingFormat = MFVideoFormat_RGB32;
inputFormat = MFVideoFormat_RGB32;
And it seems to work till the new exception in the WriteSample methods
hr = MFCopyImage(
pData, // Destination buffer.
cbWidth, // Destination stride.
(BYTE*)videoFrameBuffer, // First row in source image.
cbWidth, // Source stride.
cbWidth, // Image width in bytes.
videoHeight // Image height in pixels.
);
Apparently an Access Violation while writing in the memory.
Still trying to figure it out !
McSime

Xamarin IOS Encoding/Decoding Images from and to Base64

I am working on an application for IOS in Xamarin. I have a menu in which I request something called "Doublechecks". These doublechecks have a field with the name "Medication". In a previous working copy of the app, I simply used a string to fill this field, but now we had the idea to, instead of filling this medication field with a string, to fill it with an image. One of the tips I got was to convert a taken or chosen image to base64.
In the menu where I make a new doublecheck I have a button that pops up an actionsheet, where you can choose weather you want to pick an image from your PhotoLibrary, or take a new picture with your camera. When you've taken or chosen a picture, I use the following method to encode it to Base64:
var imageToSend = originalImage.AsJPEG (0.23f).GetBase64EncodedString (NSDataBase64EncodingOptions.None);
Where the originalImage is the image I took/chose. Now, when requesting all doublechecks, I use the following to decode it:
byte[] encodedDataAsBytes = System.Convert.FromBase64String (imageToDisplay);
string decoded = System.Text.Encoding.ASCII.GetString (encodedDataAsBytes);
NSData data = NSData.FromString (decoded, NSStringEncoding.ASCIIStringEncoding);
return UIImage.LoadFromData (data);
The method works up until the return. Somehow, the UIImage is not being constructed, and has its value null, even though the 'data' contains the decoded string.
I have searched several threads and fora, but without much avail. Any help would be much appreciated.
Why are you converting the base64 decoded data into a string ?
Since you already have the byte array you should be able to simply do:
byte[] encodedDataAsBytes = System.Convert.FromBase64String (imageToDisplay);
NSData data = NSData.FromArray (encodedDataAsBytes);
return UIImage.LoadFromData (data);
NSData method not always a good solution. You can also try following
var rawData = pixelMap.ToByteArray();
using (var provider = new CGDataProvider(rawData, 0, rawData.Length))
{
using (var colorSpace = CGColorSpace.CreateDeviceRGB())
{
var cgImage = new CGImage(
pixelMap.Width,
pixelMap.Height,
pixelMap.BitsPerComponent,
pixelMap.BytesPerPixel * ByteToBit,
pixelMap.BytesPerPixel * pixelMap.Width,
colorSpace,
CGBitmapFlags.ByteOrderDefault,
provider,
null,
true,
CGColorRenderingIntent.Default
);
return ImageSource.FromStream(() => UIImage.FromImage(cgImage).AsPNG().AsStream());
}
}
Check out my library and samples for more info about both Android and iOS bitmap from/to 2d pixel map.
https://github.com/enginkirmaci/Imaging-Library

Accurately measuring the runtime of a function in PHP and a similar one in C#

Bit of a mixture of a question, I have got the following code in PHP which just rotates and image, and times how long it takes to rotate that image:
<?php
ini_set("memory_limit", -1);
$im = imagecreatefromjpeg("test.jpg");
$time_start = microtime(true);
$rotate = imagerotate($im,90,0);
$time_end = microtime(true);
$execution_time = "Took ". ($time_end - $time_start) * 1000 ." to generate image!";
$white = imagecolorallocate($im,255,255,255);
$font = $_SERVER['DOCUMENT_ROOT']."/ppa/images/fonts/Calibri Bold.ttf";
imagettftext($rotate,15,0,20,20,$white,$font,$execution_time);
header("Content-Type: image/jpeg");
imagejpeg($rotate);
imagedestroy($im);
?>
If I run that code I get a number of around 404.000 displayed on my image, now I also have some code in C# which rotates the same image, i'm afraid that the methods i'm using to time this though may not match and I could be getting false comparisons.
Here is my C# code:
private void rotatec_Click(object sender, EventArgs e)
{
Image image1 = pictureBox1.Image;
if (image1 != null)
{
System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
image1.RotateFlip(RotateFlipType.Rotate90FlipY);
s.Stop();
string text = "Time took: {0} ms" + s.ElapsedMilliseconds;
pictureBox1.BackgroundImage = image1;
image1.Save(#".\test.jpg");
//Write to text file
System.IO.StreamWriter file = new System.IO.StreamWriter(#".\timetook.txt");
file.WriteLine(text);
file.Close();
}
else
{
MessageBox.Show("Please load an image first!");
}
}
I'm afraid that the methods i'm using to time this though may not match and I could be getting false comparisons, is that so?...
------------------------------------------------------
Updated my code, at the moment I get:
402.023 milliseconds from PHP (If i'm calculating it correctly)
148 milliseconds from C#
That seem realistic for rotating an image?
So. You are tring to measure operation rotation in different language and compare it. But first you have to make sure that your operation do the same job.
In your example it is not because input data and output data is completely different. It's internal represent of image resource. So, operations rotation do different things.
But if you include into your measure opening and writing file you could compare it.
P.S. do not forget that jpg has compression levels and set of different compression algorithms. Make sure that your output files are equal (at least similar).

how to decode mp3 file in c# using NAudio

My task is to decode a mp3 file, exclude its header, side information and the optional checksum. I just need the actual data of every frame of the mp3 file.
I have googled a lot but did't find a way !
Can any one tell me a direct way to do that. I am using NAudio to access frames using ReadNextFrame()
Any help will be appreciated.
As mentioned in http://mark-dot-net.blogspot.de/2010/11/merging-mp3-files-with-naudio-in-c-and.html you could change the code to something like that:
public static byte[] GetRawMp3Frames(string filename)
{
using(MemoryStream output = new MemoryStream()) {
Mp3FileReader reader = new Mp3FileReader(filename);
Mp3Frame frame;
while ((frame = reader.ReadNextFrame()) != null)
{
output.Write(frame.RawData, 0, frame.RawData.Length);
}
return output.ToArray();
}
}
Then you can process the frame-only bytes by doing this:
var btAllFrames = GetRawMp3Frames("MyMp3.mp3");
EDIT: Looks like this is a dupe question that was answered better here.
ORIGINAL:
Sounds like you want a full MP3 decoder that outputs the main_data chunks instead of decoding them.
Two options:
Build your own reader (complete with bit reservoir calculations for layer III), or
Remove the audio decode logic from an existing decoder and insert your output logic instead.
There are probably some tricks you can apply that would allow you to short-circuit decoding at least some of the header / side info, but that will take a thorough understanding of the specifications.
If you need a place to start for option #2, try searching for NLayer, JLayer, libmad, or "dist10 source".
Apparently NAudio uses NLayer.
This worked for me
byte[] data = File.ReadAllBytes("path/to/file.mp3");
var memStream = new System.IO.MemoryStream(results);
var mpgFile = new NLayer.MpegFile(memStream);
var samples = new float[mpgFile.Length];
mpgFile.ReadSamples(samples, 0, (int)mpgFile.Length);

NAudio to split mp3 file

I am very new to audio or mp3 stuff, was looking for a way to have a feature to split an mp3 file in C#, asp.net. After googling for a good 3-day without much of a great help, I am hoping that somebody here can point me to a right direction.
Can I use NAudio to accomplish this? Is there any sample code for that? Thanks in advance.
My final solution to split mp3 file in c# is to use NAudio. Here is a sample script for that, hope it helps someone in the community:
string strMP3Folder = "<YOUR FOLDER PATH>";
string strMP3SourceFilename = "<YOUR SOURCE MP3 FILENAMe>";
string strMP3OutputFilename = "<YOUR OUTPUT MP3 FILENAME>";
using (Mp3FileReader reader = new Mp3FileReader(strMP3Folder + strMP3SourceFilename))
{
int count = 1;
Mp3Frame mp3Frame = reader.ReadNextFrame();
System.IO.FileStream _fs = new System.IO.FileStream(strMP3Folder + strMP3OutputFilename, System.IO.FileMode.Create, System.IO.FileAccess.Write);
while (mp3Frame != null)
{
if (count > 500) //retrieve a sample of 500 frames
return;
_fs.Write(mp3Frame.RawData, 0, mp3Frame.RawData.Length);
count = count + 1;
mp3Frame = reader.ReadNextFrame();
}
_fs.Close();
}
Thanks to Mark Heath's suggestion for this.
The namespace required is NAudio.Wave.
An MP3 File is made up of a sequence of MP3 frames (plus often ID3 tags on the beginning and end). The cleanest way to split an MP3 file then is to copy a certain number of frames into a new file (and optionally bring the ID3 tags along too if that is important).
NAudio's MP3FileReader class features a ReadNextFrame method. This returns an MP3Frame class, which contains the raw data as a byte array in the RawData property. It also includes a SampleCount property which you can use to accurately measure the duration of each MP3 Frame.
The previous answers helped me get started. NAudio is the way to go.
For my PodcastTool I needed to to split podcasts at 2 minute intervals to make seeking to a specific place faster.
Here's the code to split an mp3 every N seconds:
var mp3Path = #"C:\Users\ronnie\Desktop\mp3\dotnetrocks_0717_alan_dahl_imagethink.mp3";
int splitLength = 120; // seconds
var mp3Dir = Path.GetDirectoryName(mp3Path);
var mp3File = Path.GetFileName(mp3Path);
var splitDir = Path.Combine(mp3Dir,Path.GetFileNameWithoutExtension(mp3Path));
Directory.CreateDirectory(splitDir);
int splitI = 0;
int secsOffset = 0;
using (var reader = new Mp3FileReader(mp3Path))
{
FileStream writer = null;
Action createWriter = new Action(() => {
writer = File.Create(Path.Combine(splitDir,Path.ChangeExtension(mp3File,(++splitI).ToString("D4") + ".mp3")));
});
Mp3Frame frame;
while ((frame = reader.ReadNextFrame()) != null)
{
if (writer == null) createWriter();
if ((int)reader.CurrentTime.TotalSeconds - secsOffset >= splitLength)
{
// time for a new file
writer.Dispose();
createWriter();
secsOffset = (int)reader.CurrentTime.TotalSeconds;
}
writer.Write(frame.RawData, 0, frame.RawData.Length);
}
if(writer != null) writer.Dispose();
}
these would be helpful Alvas Audio (commercial) and ffmpeg
If you want to split podcasts, copy the tracks to an audio device (swimming headers in my case) and include a little audio header made from the Text To Speech service from Google to identify the tracks. (e.g. "History of the world in a hundred objects. Episode 15. Track 1 of 4") you could check a little bash script https://github.com/pulijon/cpodcast/blob/main/cutpodcast.bash
It is prepared to add the audio header in Spanish. For other languages you should change the option -l and the string of header
gtts-cli "Corte $((10#$ntrack)) de $((10#$numtracks)). $5 " -l es --output pre_$track

Categories