Extract GPS meta data of a video using C# - c#

I have tried following libraries in c# (.net core)
Media Info
Metadata Extractor
Tag Lib
Media Tool Kit
I wasn't able to retrieve GPS metadata from any of these libraries of a video.
But for an image, it worked fine. Also, I tried the Exif tool, but no luck.
Following are some code samples I used. Looking for help on this.
// using metadata extractor
var byteArray = await File.ReadAllBytesAsync("./meta_video.mp4");
Stream stream = new MemoryStream(byteArray);
var directories = QuickTimeMetadataReader.ReadMetadata(stream);
var directories1 = ImageMetadataReader.ReadMetadata("./meta_image1.jpg");
// using tag lib
var tfile = TagLib.File.Create(#"./meta_video.mp4");
// using media tool kit
var inputFile = new MediaToolkit.Model.MediaFile {Filename = #"./meta_video.mp4"};
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
}
// using media info
string fileNameAndPath = "./video2.mp4";
var myVideo = new MediaFile(fileNameAndPath);

Related

Convert a JPG or PNG to WebP in C# .NET 6 [duplicate]

I'm writing a telegram bot that takes jpg from it's users and sends it back as stickers.
I did this correctly by downloading jpg, change the extension of file to png and upload and send it back as a sticker message to the user. as shown below:
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var filename = file.FileId + "." + file.FilePath.Split('.').Last();
var pngFileName = filename.Split('.')[0] + ".png";
using (var saveImageStream = System.IO.File.Open(pngFileName, FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
using (var stream = System.IO.File.Open(pngFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
but the these stickers don't load in telegram on IOS devices and this code just works for telegram users on android. I tried to just changing the extension of jpg file to webp but it didn't work.
after that I downloaded the standard telegram stickers and found that the standard format of stickers in telegram is webp files.
now I want to know how can I convert received jpg file to webp file.
I searched alot and just find this , found here .
using (Image image = Image.FromFile("image.jpg"))
{
Bitmap bitmap = new Bitmap(image);
WebPFormat.SaveToFile("image.webp", bitmap);
}
I added it's files to my project and I added "using LibwebpSharp;" at the top of my code, but when I add it's sample code, the VS cannot find "WebpFormat" class.
please help me and answer my question:
"How can I convert jpg to webp in C# telegram bot?"
thank you
I solved this problem in this way:
I installed Imazen.WebP nuget.
I downloaded the 32bit dll from here and added it to release folder.
I added "using Imazen.WebP;in top of my code
I used this code to convert jpg to webp.
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var jpgFileName = file.FileId + ".jpg";
using (var saveImageStream = System.IO.File.Open(jpgFileName,FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
var webpFileName = file.FileId + ".webp";
using (Bitmap bitmap = new Bitmap(jpgFileName))
{
using (var saveImageStream = System.IO.File.Open(webpFileName, FileMode.Create))
{
var encoder = new SimpleEncoder();
encoder.Encode(bitmap, saveImageStream, 20);
}
}
using (var stream = System.IO.File.Open(webpFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
System.IO.File.Delete(jpgFileName);
System.IO.File.Delete(webpFileName);
Install the following packages first using Visual Studio's NuGet package manager:
Install-Package System.Drawing.Common
Install-Package ImageProcessor
Install-Package ImageProcessor.Plugins.WebP
Then use this code for conversion:
using (var webPFileStream = new FileStream(WebpFilePath, FileMode.Create))
{
using (ImageFactory imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(File.OpenRead(OriginalImagePath))
.Format(new WebPFormat())
.Quality(100)
.Save(webPFileStream);
}
}
Imageprocessor looks like a good library to convert the image. There is a Webp plugin.
Here is an article that may help.
Code example:
using ImageProcessor;
using ImageProcessor.Plugins.WebP.Imaging.Formats;
using (var normalFileStream = new FileStream(normalImagePath, FileMode.Create))
using (var webPFileStream = new FileStream(webPImagePath, FileMode.Create))
using (var imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(image.OpenReadStream())
.Format(new WebPFormat())
.Quality(50)
.Save(webPFileStream);
}

Don't know how to transcribe wav file from Google Cloud Storage for LongRunningRecognize conversion to text in C#?

I'm able to convert audio files to text as long as they are under a minute. I need to transcribe longer files. Apparently, you have to have the file in Cloud Storage but I can't figure out if there is one command that does that or if I have to do it separately. What I'm using now is:
var credential = GoogleCredential.FromFile(GoogleCredentials);
var channel = new Grpc.Core.Channel(SpeechClient.DefaultEndpoint.ToString(), credential.ToChannelCredentials());
var speech = SpeechClient.Create(channel);
var response = speech.LongRunningRecognize(
new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
LanguageCode = "en",
},
RecognitionAudio.FromFile(waveFile));
response = response.PollUntilCompleted();
I know I need to specify a file in Cloud Storage like:
RecognitionAudio.FromStorageUri("gs://ldn-speech/" + waveFile);
But I don't know how to get the file into the gs bucket. Do I have to do that in a separate step or as part of one of the Speech API's? I'm looking for someone to show me an example.
EDIT: I found that I needed to upload the file separately and could use the credential file I had already been using in the speech recognition process: So, all I needed was:
var credential = GoogleCredential.FromFile(GoogleCredentials);
var storage = StorageClient.Create(credential);
using (var f = File.OpenRead(fullFileName))
{
fileName = Path.GetFileName(fullFileName);
storage.UploadObject(bucketName, fileName, null);
}
There is also another method of going about in your case.
As stated in your edit you indeed needed to upload the file separately to your Cloud Storage bucket.
If you are planning on transcribing long audio files (longer than 1 minute) to text you may consider using Asynchronous Speech recognition:
https://cloud.google.com/speech-to-text/docs/async-recognize#speech-async-recognize-gcs-csharp
The code sample uses Cloud Storage bucket to store raw audio input for long-running transcription processes. It also requires that you have created and activated a service account.
Here’s an example:
static object AsyncRecognizeGcs(string storageUri)
{
var speech = SpeechClient.Create();
var longOperation = speech.LongRunningRecognize(new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
SampleRateHertz = 16000,
LanguageCode = "en",
}, RecognitionAudio.FromStorageUri(storageUri));
longOperation = longOperation.PollUntilCompleted();
var response = longOperation.Result;
foreach (var result in response.Results)
{
foreach (var alternative in result.Alternatives)
{
Console.WriteLine($"Transcript: { alternative.Transcript}");
}
}
return 0;
}
(1) I found that I did indeed need to upload the file separately to cloud storate. (2) could use the credential file I had already been using in the speech recognition process: So, all I needed was:
var credential = GoogleCredential.FromFile(GoogleCredentials);
var storage = StorageClient.Create(credential);
using (var f = File.OpenRead(fullFileName))
{
fileName = Path.GetFileName(fullFileName);
storage.UploadObject(bucketName, fileName, null);
}
Once in Cloud storage, I could transcribe it as I originally thought. Then delete the file after the process was complete with:
var credential = GoogleCredentials;
var storage = StorageClient.Create(credential);
using (var f = File.OpenRead(fullFileName))
{
fileName = Path.GetFileName(fullFileName);
storage.DeleteObject(bucketName, fileName);
}

C# Transform Data in ETL Process

I am learning the ETL process in C# and have already extracted and read the sample CSV data but am unsure at what to do to transform it properly.
I have been using this website as a reference at how to transform data, but I am unsure on how to apply it to my sample data (below).
name,gender,age,numKids,hasPet,petType
Carl,M,43,2,true,gecko
Jake,M,22,1,true,snake
Cindy,F,53,3,false,null
Matt,M,23,0,true,dog
Ally,F,28,1,false,null
Megan,F,42,2,false,null
Carly,F,34,4,true,cat
Neal,M,27,2,false,null
Tina,F,21,2,true,pig
Paul,M,1,3,true,chicken
Below is how I extracted the data from the CSV file using CSVHelper
using (FileStream fs = File.Open(#"C:\Users\Grant\Documents\SampleData4.csv", FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
{
CsvConfiguration csvConfig = new CsvConfiguration()
{BufferSize = bufferSize, AllowComments = true};
using (var csv = new CsvReader(sr, csvConfig))
{
while (csv.Read())
{
var name = csv.GetField<string>(0);
var gender = csv.GetField<string>(1);
var age = csv.GetField<int>(2);
var numKids = csv.GetField<int>(3);
var hasPet = csv.GetField<bool>(4);
var petType = csv.GetField<string>(5);
}
}
}
If you need me to provide additional details, just ask below.
Although a little late, I still would like to add an answer:
To create you own ETL process and Data Flow with C#, I would recommend you the nuget package ETLBox (https://etlbox.net). It will enable you to write a ETL data flow, where the CSV reader implementation is already wrapped in a CSVSource object. E.g., you would have to do the following to load data from a CSV into a database:
Defina a CSV source
CSVSource sourceOrderData = new CSVSource("demodata.csv");
Optionally define a row transformation:
RowTransformation<string[], Order> rowTrans = new RowTransformation<string[], Order>(
row => new Order(row)
);
Define the destination
DBDestination<Order> dest = new DBDestination<Order>("dbo.OrderTable");
Link your ETL data pipeline together
sourceOrderData.LinkTo(rowTrans);
rowTrans.LinkTo(dest);
Finally start the dataflow (async) and wait for all data to be loaded.
source.Execute();
dest.Wait();

WP8/VS2013 MediaLibrary Songs collection is empty

I'm having a play with writing a mp3 player app for WP8, using MediaLibrary to handle the phone's own mp3 collection.
I want to test the result in the phone emulator on VS2013, but when I use the following code:
using (MediaLibrary library = new MediaLibrary())
{
SongCollection songs = library.Songs;
Song song = songs[0];
MediaPlayer.Play(song);
}
The song collection is empty, presumably because VS doesn't have any knowledge of a media library with songs in.
Is there any way to test this in the emulator using a fake medialibrary or for VS to use windows' media library? I just want to see (or hear) the code working before I proceed :)
I have managed to find a workaround!
If you add an mp3 file to the app's assets, the following code will add the mp3 to the media player library:
private void AddSong()
{
Uri file = new Uri("Assets/someSong.mp3", UriKind.Relative);
//copy file to isolated storage
var myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
var fileStream = myIsolatedStorage.CreateFile("someSong.mp3");
var resource = Application.GetResourceStream(file);
int chunkSize = 4096;
byte[] bytes = new byte[chunkSize];
int byteCount;
while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)
{
fileStream.Write(bytes, 0, byteCount);
}
fileStream.Close();
Microsoft.Xna.Framework.Media.PhoneExtensions.SongMetadata metaData = new Microsoft.Xna.Framework.Media.PhoneExtensions.SongMetadata();
metaData.AlbumName = "Some Album name";
metaData.ArtistName = "Some Artist Name";
metaData.GenreName = "test";
metaData.Name = "someSongName";
var ml = new MediaLibrary();
Uri songUri = new Uri("someSong.mp3", UriKind.RelativeOrAbsolute);
var song = Microsoft.Xna.Framework.Media.PhoneExtensions.MediaLibraryExtensions.SaveSong(ml, songUri, metaData, Microsoft.Xna.Framework.Media.PhoneExtensions.SaveSongOperation.CopyToLibrary);
}
I also needed to add:
using System.IO.IsolatedStorage;
I would love to claim credit for this, but I found the answer here:
http://social.msdn.microsoft.com/forums/wpapps/en-US/f5fa73da-176b-4aaa-8960-8f704236bda5/medialibrary-savesong-method
By default the media library on the emulator is empty. I also do not think it is possible to automagically hook up your dev machine's music folder to the emulator to test that way. It might be possible to manually configure the emulated phone with an email account! and save music onto it that way, but even if that worked you'd have to do it each and every time you restart the emulator.
Best way to test would be t deploy to a real device.

How to merge 2 video files together in C#?

I need to merge multiple video files (.wmv) together to get a single wmv file.
How can I do it?
You can do that easily Use Splicer, it free and open source in C#
Simplify developing applications for editing and encoding audio and video using DirectShow
Example:
using Splicer;
using Splicer.Timeline;
using Splicer.Renderer;
string firstVideoFilePath = #"C:\first.avi";
string secondVideoFilePath = #"C:\second.avi";
string outputVideoPath = #"C:\output.avi";
using (ITimeline timeline = new DefaultTimeline())
{
IGroup group = timeline.AddVideoGroup(32, 720, 576);
var firstVideoClip = group.AddTrack().AddVideo(firstVideoFilePath);
var secondVideoClip = group.AddTrack().AddVideo(secondVideoFilePath, firstVideoClip.Duration);
using (AviFileRenderer renderer = new AviFileRenderer(timeline, outputVideoPath))
{
renderer.Render();
}
}
You can split and join video files using DirectShow or the Windows Media Encoder.
DirectShowNet library has examples which you might find useful. I think its called DESCombine.

Categories