Video Thumbnail creation in landscape or portrait mode - c#

I'm using Nreco Video converter to create video thumbnails. Here is the C# code that I'm using.
(new NReco.VideoConverter.FFMpegConverter()).GetVideoThumbnail(fileSource, thumbNailPath, (float)0.1);
It simply works fine. The only issue being the orientation. The videos for which I'm trying to create thumbnails are recorded on a mobile app. So irrespective of whether the video is in portrait or landscape mode, the thumbnail generated is randomly in portrait or landscape mode.
Does any one know how to create a thumbnail of a video in a particular mode(landscape or portrait).

There is a rotation-parameter in video files that you can read by using various other ffmpeg wrapper libraries. Many players use it to actually rotate the screen. See here. As NReco does not support this directly, you would have to read this value with some other library and use it to rotate the jpeg in the stream.
I suggest using a ffmpeg wrapper where you can directly invoke ffmpeg process instances, as ffmpeg is able to read various properties from the file.

You can use ffmpeg for getting rotation from video metadata and apply appropriate rotation filter during thumbnail extraction. Since NReco VideoConverter is a .NET ffmpeg wrapper it also can be used for doing that:
Extract video orientation metadata from ffmpeg console (LogReceived event) with Invoke or ConvertMedia methods that actually doesn't perform any conversion. Rotation data can be matched with simple regex.
Compose FFMpeg arguments for appropriate rotatation filter (like: -vf "transpose=1" )
Extract thumbnail with ConvertMedia method that accepts extra ffmpeg command line arguments (see code snippet below)
(internally GetVideoThumbnail uses ConvertMedia method):
var thumbSettings = new ConvertSettings() {
VideoFrameCount = 1,
VideoFrameRate = 1,
MaxDuration = 1, // extract exactly 1 frame
Seek = 0, // frame seek position
CustomOutputArgs = String.Format(" -vf \"{0}\"", rotateFilter ) // rotation filter parameters
};
ffMpegConverter.ConvertMedia(inputFile1, null, thumbJpegOutputStream, "mjpeg", thumbSettings);
As result you will get video thumnail rotated according to video orientation metadata. Full code that implements all steps can be found in VideoConverter package (Rotate example).

Related

AviReader - getNext

I'm using SharpAvi's AviWriter to create AVI files. I can get any standard video player to play these AVI files. 20 frames per second with no compression. using example from this link
so that seems to be working fine.
failing to find SharpAVi's AviReader anywhere I've resorted to using AForge.Video.VFW's AVIReader but it can only show me a black screen for each frame before index 128 and then if fails to get next frame.
the example I'm using is straighforward
// instantiate AVI reader
AVIReader reader = new AVIReader( );
// open video file
reader.Open( "test.avi" );
// read the video file
while ( reader.Position - reader.Start < reader.Length )
{
// get next frame
Bitmap image = reader.GetNextFrame( );
// .. process the frame somehow or display it
}
I have my app's Build set to x86 to accommodate both these AVI apps 32 bit settings.
and using AForge.Video.VFW AVIWriter fails to write files with more than some 500 +/- frames.(video player needs to rebuild index and C#IDE "fails opening AVI file".
does SharpAVI have an AVIReader? because I haven't found one.

How to generate empty or blank videolayer to .mp4 which is encoded from .mp3 (or other audio-only) files using Azure Media Services v3?

Problem summarized
We're using Azure Media Services v3 for streaming media files with Azure Media Player. Currently I'm trying to add an option to stream .mp3 with AES encryption.
Uploading and encoding the file works fine, I can see the generated .mp4 file and I can even play it if I download it from the blob. The problem is when I try to stream it in Azure Media Player I get the following error in the player:
image
This is because Azure Media Player doesn't support streaming audio only files as it is stated in its documentation:
May work in some techs for Adaptive Streaming but is currently not supported and does not work in AzureHtml5JS.
What I've tried
So I've tried to add blank/empty h264Layer to the transform job so the encoded file wouldn't be audio-only. I've found some questions regarding this problem, like this, however my problem is still unresolved.
I've also found this suggestion, which led me to Azure Media Services v2 documentation page but I think it isn't what I need.
I've also seen this note:
Many of the advanced Media Services v2 features of the Media Encoder Standard are currently not available in v3. For more information, see feature gaps.
I set the encoding preset to "EncoderNamedPreset.AACGoodQualityAudio". Then to "EncoderNamedPreset.H264SingleBitrate720p" just to see if it creates an empty video layer but the result was the same: the video file was created in its own asset but I wasn't able to stream it.
I've tried to create my own encoder preset with empty H264Layer like this:
new StandardEncoderPreset(
codecs: new Codec[]
{
new AacAudio(
channels: 2,
samplingRate: 48000,
bitrate: 128000,
profile: AacAudioProfile.AacLc
),
new H264Video(
keyFrameInterval: TimeSpan.FromSeconds(2),
sceneChangeDetection: true,
layers: new H264Layer[]
{
new H264Layer (
bitrate: 1, // Units are in bits per second
width: "1",
height: "1",
label: "SD" // This label is used to modify the file name in the output formats
) }
)
},
formats: new Format[]
{
new Mp4Format(filenamePattern:"Video-{Basename}-{Label}-{Bitrate}{Extension}")
}
)
Result while creating Transform:
Exception: Operation returned an invalid status code 'BadRequest'
With blank layer
new H264Layer (
bitrate: 0, // Units are in bits per second
width: "0",
height: "0",
label: "SD" // This label is used to modify the file name in the output formats
)
Result while creating transform:
Exception: Operation returned an invalid status code 'BadRequest'
H264Layer without constructor parameters
new H264Layer()
Result:
Transform is created.
Same error in AMP when trying to stream it.
The video playback was aborted due to a corruption problem or because the video used features your browser did not support. (0x20400003)
Expected result
The expected result would be any kind of file what could be streamed by Azure Media Player. I guess this should be achieved somehow adding a blank/empty H264 layer to the encoded file but I can't figure out how to do it in Azure Media Services v3.
Adding the response, that was conveyed offline, to this post:
You are correct, that Azure Media Player currently requires a video
track
When using v2 APIs, there is a way to insert a video track when encoding an audio-only source
That flag is currently not exposed in our v3 schema
However, should be able to use a v3 Preset like AdaptiveStreaming – it encodes the audio, and generates a ‘blank video’ track
Thanks,
Anil

How to write and view converted pdfs to and from memory?

Right now I am using ghostscript in Unity to convert pdfs to jpgs and view them in my project.
Currently it flows like so:
-Pdfs are converted into multiple jpegs (one for each page)
-The converted jpegs are written to disk
-They are then read in by bytes into a 2D texture
-And this 2D texture is assigned to a GameObjects RawImage component
This works perfectly in Unity, but... (now comes the hiccup) my project is intended to run on the Microsoft Hololens.
The Hololens runs on the Windows 10 API, but in a limited capacity.
Where the issue arises is when I try to convert pdfs and view them on the Hololens. Quite simply, the Hololens cannot create or delete files outside of its known folders (Pictures, Documents, etc).
My imagined solution to this problem is to instead of write the converted jpeg files to disk, write them to memory and view them from there.
In talking with GhostScript devs, I was told GhostScript.NET does what I am looking to do - convert pdfs and view them from memory (It does this with the Rasterizer/Viewer classes, I believe, but again I don't understand it quite well).
I've been lead to look at the latest GhostScript.NET docs to route out how this is done, but I simply don't understand them well enough to approach this.
My question is then, based on how I'm using ghostscript now, how do I use GhostScript.NET in my project to write the converted jpegs into memory and view them there?
Here's how I'm doing it now (code-wise):
//instantiate
byte[] fileData;
Texture2D tex = null;
//if a PDF file exists at the current head path
if (File.Exists(CurrentHeadPath))
{
//Transform pdf to jpg
PdfToImage.PDFConvert pp = new PDFConvert();
pp.OutputFormat = "jpeg"; //format
pp.JPEGQuality = 100; //100% quality
pp.ResolutionX = 300; //dpi
pp.ResolutionY = 500;
pp.OutputToMultipleFile = true;
CurrentPDFPath = "Data/myFiles/pdfconvimg.jpg";
//this call is what actually converts the pdf to jpeg files
pp.Convert(CurrentHeadPath, CurrentPDFPath);
//this just loads the first image
if (File.Exists("Data/myFiles/pdfconvimg" + 1 + ".jpg"))
{
//reads in the jpeg file by bytes
fileData = File.ReadAllBytes("Data/myFiles/pdfconvimg" + 1 + ".jpg");
tex = new Texture2D(2, 2);
tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
//Read Texture into RawImage component
PdfObject.GetComponent<RawImage>().texture = tex;
PdfObject.GetComponent<RawImage>().rectTransform.sizeDelta = new Vector2(288, 400);
PdfObject.GetComponent<RawImage>().enabled = true;
}
else
{
Debug.Log("reached eof");
}
}
The convert function is from a script called PDFConvert which I obtained from code project. Specifically How To Convert PDF to Image Using Ghostscript API.
From the GhostScript.Net documentation, take a look at the example code labeled: "Using GhostscriptRasterizer class". Specifically the following lines:
Image img = _rasterizer.GetPage(desired_x_dpi, desired_y_dpi, pageNumber);
img.Save(pageFilePath, ImageFormat.Png);
The Image class seems to be part of the System.Drawing package, and System.Drawing.Image has another Save method where the first parameter is a System.IO.Stream.

EMGU QueryFrame returns "streaky" Image over RTSP

I have a HD network camera that I am trying to grab frames over rtsp and using the following code:
//in Form_Load
Application.Idle += getNextFrame;
And the Event Handler:
private void getNextFrame(object sender, EventArgs ags)
{
//where _imgCount is the total image Grabs
lbl_Count.Text = _imgCount++.ToString();
// and ibLive is a Emgu ImageBox
ibLive.Image = capAxis.QueryFrame().Resize(640, 480, INTER.CV_INTER_AREA);
}
When I start the program, it'll grab 20-40 frames before the "streakiness" appears at the bottom of the screen. It's always on the bottom of the image, but some times it takes up half the screen.
The stream resolution is 1920x1080 and it's using mjpeg. I tried switching to h.264 but had the same results.
I am using Emgu version x86-2.4.0.1717
Any Ideas?
Thanks.
I know this is an old question but I ran into the same problem recently.
I would recommend using another streaming library. Eg.
http://net7mma.codeplex.com/
http://www.fluorinefx.com/
If you really need to stream using EMGU then create a stream profile with a lower resolution or higher compression. I set compression to 30 and used the same resolution then provided the stream profile name in the rtsp url. (Assuming you're using an Axis camera like me capAxis)
Capture cap = new Capture(#"rtsp://10.0.0.1/axis-media/media.amp?videocodec=h264&streamprofile=rtspstream");
I have the same problem like that and I have solved it by myself. I used iSpy to know url of my ONVIF Ip Camera. My IP Camera's url is rtsp://192.168.1.xxx:554//user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream
For stream = 0, my IP Cam is running in HD resolution (1280 x 720) and that resolution makes a streaky result of my image. So there were two options of URL that iSpy gave, and the other one is just different in stream. I changed stream = 1 for low resolution (352 x 288) and the image result is good ! There's no streaky in my image. Something that I learned from this problem was using RTSP you must use it in low resolution. High resolution will make the image result not good. Hope it can help your problem.
Regards,
Alfonsus Dhani
At the end of Capture string add this "?tcp"
Capture cap = new Capture(#"rtsp://10.0.0.1/axis-media/media.amp?videocodec=h264&streamprofile=rtspstream?tcp");
EDIT
This is my code, and yes, it works, I'am using an IP cam DAHUA.
Capture cap = Capture(#"rtsp://admin:12345#10.0.0.01:554/cam/realmonitor?channel=1&subtype=01?tcp");
A late reply but may help someone facing similar challenged.
Emgu's capabilities to deal with RTSP streams are limited and not stable. I was facing similar issues as discussion in this question,
Unable to use EMGU CV to grab images from RTSP stream continuously
The solution was to use RTSPClientSharp which works like a charm.
( https://github.com/BogdanovKirill/RtspClientSharp )

How do I get a Video Thumbnail in .Net?

I'm looking to implement a function that retrieves a single frame from an input video, so I can use it as a thumbnail.
Something along these lines should work:
// filename examples: "test.avi", "test.dvr-ms"
// position is from 0 to 100 percent (0.0 to 1.0)
// returns a bitmap
byte[] GetVideoThumbnail(string filename, float position)
{
}
Does anyone know how to do this in .Net 3.0?
The correct solution will be the "best" implementation of this function.
Bonus points for avoiding selection of blank frames.
I ended up rolling my own stand alone class (with the single method I described), the source can be viewed here. Media browser is GPL but I am happy for the code I wrote for that file to be Public Domain. Keep in mind it uses interop from the directshow.net project so you will have to clear that portion of the code with them.
This class will not work for DVR-MS files, you need to inject a direct show filter for those.
This project will do the trick for AVIs: http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx
Anything other formats, you might look into directshow. There are a few projects that might help:
http://sourceforge.net/projects/directshownet/
http://code.google.com/p/slimdx/
1- Get latest version of ffmpeg.exe from : http://ffmpeg.arrozcru.org/builds/
2- Extract the file and copy ffmpeg.exe to your website
3- Use this Code:
Process ffmpeg;
string video;
string thumb;
video = Server.MapPath("first.avi");
thumb = Server.MapPath("frame.jpg");
ffmpeg = new Process();
ffmpeg.StartInfo.Arguments = " -i "+video+" -ss 00:00:07 -vframes 1 -f image2 -vcodec mjpeg "+thumb;
ffmpeg.StartInfo.FileName = Server.MapPath("ffmpeg.exe");
ffmpeg.Start();
There are some libraries at www.mitov.com that may help. It's a generic wrapper for Directshow functionality, and I think one of the demos shows how to take a frame from a video file.
This is also worth to see:
http://www.codeproject.com/Articles/13237/Extract-Frames-from-Video-Files

Categories