C# Reading Video Metadata in Windows (Title,description,year) - c#

Hey everyone just trying to make a program that browses video files and reads the title and description from the files metadata. I found some docs from microsoft here giving whats needed but how do I access these functions? what using namespaces are needed in c#? I would love any help that can be provided.

In that link you posted, scroll to the bottom and click "Shell Metadata Providers". There's more more information and some sample C++ code.
Here are some other relevant links:
Reading/Writing metadata of audio/video files
http://www.codeproject.com/Articles/14535/Accessing-WMF-metadata-with-C
https://social.msdn.microsoft.com/Forums/pt-BR/0f36a3b2-4d3d-4842-88a4-bea493bbbace/read-video-filemov-avi-mpg-etc-meta-data?forum=csharpgeneral
https://web.archive.org/web/20170225230114/https://stackoverflow.com/questions/7396265/c-sharp-to-read-properties-of-video-files
Sorry I can't give you anything more concrete, however it looks like some tag libraries (i.e. for reading MP3 metadata) may work as well, as the metadata for videos seems to be stored in a similar, if not identical, format. That being said, you can give TagLib# a shot.
https://www.nuget.org/packages/taglib/

I've made a simple C# code (portable to Unity, too) csatomreader. It's optimized for speed and can read the atoms over HTTP, too.
E.g. Get title:
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
var mp4Reader = new AtomReader(stream);
string value = mp4Reader.GetMetaAtomValue(AtomReader.TitleTypeName);
Console.WriteLine($"{atomTypeName}: {value}");
}
If you need to get more metadata values at once, then iterate over ParseAtoms(), e.g. see the GetMetaAtomValue() source.

Related

Saving Bigger Files with TTS Android

Recently i used android TTS - I save the file as MP3 and play it using MediaPlayer so users can pause/resume etc.
It all works fine other than when i have a large text it just does not work.
I read that the android TTS has the limit of 4000 CHs? What should i do to tackle large amount of text?
The following is the code i am using to save MP3
Android.Speech.Tts.TextToSpeech textToSpeech;
...
textToSpeech = new Android.Speech.Tts.TextToSpeech(this, this, "com.google.android.tts");
...
textToSpeech.SynthesizeToFile(ReadableText, null, new Java.IO.File(System.IO.Path.Combine(documentsPath, ID + "_audio.mp3")), ID);
The following is the code i am using to playback the audio
MediaPlayer MP = new MediaPlayer();
...
MP.SetDataSource(System.IO.Path.Combine(documentsPath, ID + "_audio.mp3"));
MP.Prepare();
MP.Start();
It works for small amount of text but not for large text.
File gets saved (most likely just a corrupt file) because when i play it i get the following error
setDataSoruceFD failed: status=0x80000000
Java Solution is also acceptable
FYI - The question is about the max text size as I can generate the file for smaller text
Cheers
In Android ASOP (at least since API-18), TextToSpeech.MaxSpeechInputLength is set to 4000.
Note: OEMs could change this value in their OS image, so it would be wise to check the value and not make any assumptions.
Note: You are naming the output with an .mp3 extension, but by default the files created will be .wav formatted, some speech engines do support other formats/bitrate/etc. but you are passing null for the parameters.
Unless you want to deal with properly joining multiple wave files, I would recommend that you break your text into smaller parts and synthesize multiple files.
You can then play these back in sequence (using the MediaPlayer Completion event|listener).

Creating embedded resource in C# class library if it doesn't exist

I have an issue with a class library; I am preparing a library with an interface that represents a specific data storage signature. The purpose is to use the interface as a basis for implementing a number of specific classes storing configuration information in different formats (text files, xml files, etc.) while retaining the same usage profile to the application using it. I have a problem, though. In this case I am trying to embed an xml file as a resource - this file is one type of format to store configuration data. The file is located as an embedded resource in a subfolder to the project, as shown in the attached illustration.
In the following code snippet it is shown how I have implemented the functionality until now.
public ConfigInfoXmlSource()
{
if (!string.IsNullOrEmpty(Settings.Default.CurrentConfigFile))
FileNameAndPath = Settings.Default.CurrentConfigFile;
else
FileNameAndPath = DefaultConfigFileName + DefaultFileExtension;
// Prepare XML.
System.Reflection.Assembly a = Assembly.GetExecutingAssembly();
XmlDocument doc = new XmlDocument();
Stream manifestResourceStream =
a.GetManifestResourceStream("TestTool.Config.Config1.xml");
if (manifestResourceStream == null)
{
// ???
}
...
doc.Load(manifestResourceStream);
...
}
In the section marked "Prepare XML" I am trying to read a stream from the embedded resource. After the reading, it is tested whether a stream was indeed created. If the file is found, the manifestResourceStream will contain the xml data - so far so good. The problem arises if the file for some reason has been accidentally deleted - in that case I want to create a new file as an embedded resource to replace the deleted file. That is supposed to happen in the conditional in the part shown as "???".
I have tried everything I could think of, searched Google for answers, etc. - to no avail.
Does anyone have a clue to how this is accomplished? Any help will be greatly appreciated.
Thanks in advance.
Best regards.
If you have a embedded resource,it is built into your binaries.It is not an physical file,rather something which is present inside the built file(dll in this case).So,once it is included,I do not think it can ever be deleted. As per my knowledge embedded resource can only be set while building your project binaries and you can not explicitly do it at runtime as it is not needed due to reasons mentioned above.

Getting MP4 File Duration with DirectShow

I need to get the duration of an mp4 file, preferably as a double in seconds. I was using DirectShow (see code below), but it keeps throwing a particularly unhelpful error. I'm wondering if someone has an easy solution to this. (Seriously, who knew that getting that information would be so difficult)
public static void getDuration(string moviePath)
{
FilgraphManager m_objFilterGraph = null;
m_objFilterGraph = new FilgraphManager();
m_objFilterGraph.RenderFile(moviePath);
IMediaPosition m_objMediaPosition = null;
m_objMediaPosition = m_objFilterGraph as IMediaPosition;
Console.WriteLine(m_objMediaPosition.Duration);
}
Whenever I run this code, I get the error: "Exception from HRESULT: 0x80040265"
I also tried using this: Getting length of video
but it doesn't work either because I don't think that it works on MP4 files.
Seriously, I feel like there has to be a much easier way to do this.
Note: I would prefer to avoid using exe's like ffmpeg and then parsing the output to get the information.
You are approaching the problem correctly. You need to build a good pipeline starting from source .MP4 file and up to video and audio renderers. Then IMediaPosition.Duration will get you what you want. Currently you are getting VFW_E_UNSUPPORTED_STREAM because you cannot build the pipeline.
Note that there is no good support for MPEG-4 in DirectShow in clean Windows, you need a third party parser installed to add missing blocks. This is the likely cause of your problem. There are good Free DirectShow Mpeg-4 Filters available to fill this gap.
The code sample under the link Getting length of video is basically valid too, however it uses deprecated component which in additional make additional assumptions onto the media file in question. Provided that there is support for .MP4 in the system, IMediaPosition.Duration is to give you what you look for.
You can use get_Duration() from IMediaPosition interface.
This return a double value with the video duration in seconds.
Double Lenght;
m_FilterGraph = new FilterGraph()
//Configure the FilterGraph()
m_mediaPosition = m_FilterGraph as IMediaPosition;
m_mediaPosition.get_Duration(out Length);
Using Windows Media Player Component also, we can get the duration of the video.
I hope that following code snippet may help you guys :
using WMPLib;
// ...
var player = new WindowsMediaPlayer();
var clip = player.newMedia(filePath);
Console.WriteLine(TimeSpan.FromSeconds(clip.duration));
and don't forget to add the reference of wmp.dll which will be
present in System32 folder.

Create Video out of image files?

I'm trying to make a video out of a folder full of jpeg files. I tried Google, and everybody is stuck with this. I have downloaded the WM SDK and the Encoder, but since the moment I don't know their object model I cant do much.
Does somebody here have some code WORKING about how to create a WMV or an AVI or a MPEG video file out of a folder full of jpegs? (In C#)
I can see on the answers that apparently there is no way to do it from C#, just using a third party. I will check your suggestions.
Take a look at Corinna John's AVIFile wrapper. I used it in the AVI output plugin for Cropper.
VirtualDub is capable of making a video out of several image files. Here's a quite overview of how to do it.
FFMPEG, as CptSkippy mentioned, also has this feature.
See the AVBlocks Slideshow sample. It creates a video (like MP4) from images. The input is a series of JPEG images. The output is configured with an AVBlocks preset.
Try via NuGet "accord.extensions.imaging.io", then I wrote the following little function:
private void makeAvi(string imageInputfolderName, string outVideoFileName, float fps = 12.0f, string imgSearchPattern = "*.png")
{ // reads all images in folder
VideoWriter w = new VideoWriter(outVideoFileName,
new Accord.Extensions.Size(480, 640), fps, true);
Accord.Extensions.Imaging.ImageDirectoryReader ir =
new ImageDirectoryReader(imageInputfolderName, imgSearchPattern);
while (ir.Position < ir.Length)
{
IImage i = ir.Read();
w.Write(i);
}
w.Close();
}
It reads all images from a folder and makes a video out of them.
If you want to make it nicer you could probably read the image dimensions instead of hard coding, but you got the point.
Have you considered using FFMPEG? I've used it to create thumbnails from video in several projects.
I finally settled on Splicer. Free, simple to use, and it works. More info at Working way to make video from images in C#

How do I get a C# WebBrowser control to show jpeg files (raw)?

Does anyone know in .Net 2.0 - .Net 3.5 how to load a jpeg into a System.Windows.Forms.WebControl as a byte-array and with the right mimetypes set so it will show?
Something like:
webBrowser1.DocumentStream = new MemoryStream(File.ReadAllBytes("mypic.jpg"));
webBrowser1.DocumentType = "application/jpeg";
The webBrowser1.DocumentType seems to be read only, so I do not know how to do this. In general I want to be able to load any kind of filesource with a mimetype defined into the browser to show it.
Solutions with writing temp files are not good ones. Currently I have solved it with having a little local webserver socket listener that delivers the jpeg I ask for with the right mimetype.
UPDATE: Since someone deleted a answer-my-own question where I had info that others could use, I will add it as an update instead. (to those who delete that way, please update the questions with the important info).
Sample solution in C# here that works perfectly: http://www.codeproject.com/KB/aspnet/AspxProtocol.aspx
You have to implement an async pluggable protocol, e.g. IClassFactory, IInternetProtocol... Then you use CoInternetGetSession to register your protocol. When IE calls your implementation, you can serve your image data from memory/provide mime type.
It's a bit tedious, but doable. Look at IInternetProtocol and pluggable protocols documentation on MSDN.
You cannot do it. You cannot stuff images into Microsoft's web-browser control.
The limitation comes from the IWebBrowser control itself, which .NET wraps up.
If you want a total hack, try having your stream be the HTML file that only shows your picture. You lose your image byte stream and will have to write the image to disk.
I do not know whether the WebBrowser .NET control supports this, but RFC2397 defines how to use inline images. Using this and a XHTML snippet created on-the-fly, you could possibly assign the image without the need to write it to a file.
Image someImage = Image.FromFile("mypic.jpg");
// Firstly, get the image as a base64 encoded string
ImageConverter imageConverter = new ImageConverter();
byte[] buffer = (byte[])imageConverter.ConvertTo(someImage, typeof(byte[]));
string base64 = Convert.ToBase64String(buffer, Base64FormattingOptions.InsertLineBreaks);
// Then, dynamically create some XHTML for this (as this is just a sample, minimalistic XHTML :D)
string html = "<img src=\"data:image/" . someImage.RawFormat.ToString() . ";base64, " . $base64 . "\">";
// And put it into some stream
using (StreamWriter streamWriter = new StreamWriter(new MemoryStream()))
{
streamWriter.Write(html);
streamWriter.Flush();
webBrowser.DocumentStream = streamWriter.BaseStream;
webBrowser.DocumentType = "text/html";
}
No idea whether this solution is elegant, but I guess it is not. My excuse for not being sure is that it is late at night. :)
References:
RFC2397
Image to base64 encoded string
IE only support 32KB for inline images in base64 encoding, so not a good solution.
Try the res: protocol.
I haven't tried it with a .net dll but this post says it should work. Even if it does require a C++ dll it's much simpler to use as far as coding goes.
I've created a post that show you how here that shows you how to create the resource script and use the res: protocol correctly.

Categories

Resources