I am trying to post a video to Twitter using Tweetinvi library:
byte[] video = DownloadBlobFromUrl(parameters.VideoUrl);
IMedia media = Upload.ChunkUploadBinary(new UploadQueryParameters { Binaries = new List<byte[]> { video }, MediaType = "video/mp4", MediaCategory = "tweet_video", MaxChunkSize = VIDEO_MB_CHUNK_SIZE * 1024 * 1024 });
publishParameters.Medias = new List<IMedia> { media };
ITweet tweet = Tweet.PublishTweet(message, publishParameters);
The problem is that publishing fails, unless I add, before publishing, some sort of sleep, like:
await Task.Delay(25000);
With delay it works. Interesting is the fact that IMedia's member HasBeenUploaded is set to true. I also tried using chunk upload, but with the same result. How can I wait until video is fully uploaded to Twitter, assuming this is the issue?
I am the developer of Tweetinvi.
The problem you are encountering is a problem of the Twitter UPLOAD API. The problem is that when an upload completes it takes between few milliseconds up to 1 second for their upload service to process it and make it available to you.
From there you have 2 solutions.
Solution 1 (simplicity)
Don't specify the MediaCategory and use the classical Upload as followed:
var videoBinary = File.ReadAllBytes("file_path");
var videoMedia = Upload.UploadVideo(videoBinary);
Tweet.PublishTweet("test", new PublishTweetOptionalParameters()
{
Medias = { videoMedia }
});
This video should be available straight away. But I have experienced times when a delay is required. Therefore I usually add a delay of 500ms for Twitter servers to be ready for the incoming Tweet.
Solution 2 (amplify_video)
amplify_video is a more robust solution as it is the solution provided by Twitter to solve the delay problem.
var videoBinary = File.ReadAllBytes(#"C:\Users\linvi\Pictures\mov_bbb.mp4");
var videoMedia = Upload.UploadVideo(videoBinary, "video/mp4", "amplify_video");
var isProcessed = videoMedia.UploadedMediaInfo.ProcessingInfo.State == "succeeded";
var timeToWait = videoMedia.UploadedMediaInfo.ProcessingInfo.CheckAfterInMilliseconds;
while (!isProcessed)
{
Thread.Sleep(timeToWait);
// The second parameter (false) informs Tweetinvi that you are manually awaiting the media to be ready
var mediaStatus = Upload.GetMediaStatus(videoMedia, false);
isProcessed = mediaStatus.ProcessingInfo.State == "succeeded";
timeToWait = mediaStatus.ProcessingInfo.CheckAfterInMilliseconds;
}
I realize that this is complicated but few people uses amplify_video.
In the next release I will add a new method that will do all this logic automatically for you.
If you want to be informed when this feature is released you can find the work item here : https://github.com/linvi/tweetinvi/issues/347.
I will also provide a new enum for ProcessingInfo.State (https://github.com/linvi/tweetinvi/issues/348).
I hope this answer helps you.
Have a great day.
Found an answer, not so elegant, but it works. You have to set the media category to amplify_video. For anyone else with this issue:
byte[] video = DownloadBlobFromUrl(parameters.VideoUrl);
IMedia media = Upload.ChunkUploadBinary(new UploadQueryParameters { Binaries = new List<byte[]> { video }, MediaType = "video/mp4", MediaCategory = "amplify_video", MaxChunkSize = VIDEO_MB_CHUNK_SIZE * 1024 * 1024 });
publishParameters.Medias = new List<IMedia> { media };
IUploadedMediaInfo status = Upload.GetMediaStatus(media);
int numberOfTries = 1;
while (status.ProcessingInfo.State != "succeeded" && numberOfTries < VIDEO_UPLOAD_TRY_COUNT)
{
numberOfTries++;
await Task.Delay(VIDEO_UPLOAD_WAIT_SECONDS * 1000);
status = Upload.GetMediaStatus(media);
}
if (status.ProcessingInfo.State == "succeeded")
{
tweet = Tweet.PublishTweet(message, publishParameters);
return tweet.IdStr;
}
Related
I just converted one of my apps to target Android API 9 (was targeting API 8); now when notifications are sent out, the volume of media is lowered and never comes back to full volume.
The app uses WebView to play media files. This was not happening prior to targeting API 9. I had to convert the app into level 9 so that I could upload to the Google Play Store. I am running a Samsung S7 which was originally designed for API level 6 (with the OS upgraded to 8.0), not sure if that has something to do with the issue. Another detail is that I use Xamarin.Android for development, not sure if that matters either.
Additionally, I forced the notifications to play a blank sound (a very short[couple ms] blank mp3) in the same build that I converted the app to target API 9:
var channelSilent = new Android.App.NotificationChannel(CHANNEL_ID, name + " Silent", Android.App.NotificationImportance.High)
{
Description = description
};
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build()
//blank is blank mp3 file with nothing in it, a few ms in duration
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3")
channelSilent.SetSound(uri, alarmAttributes);
...so it could also be the blank sound that is causing the ducking to malfunction, not the API change. Is there something to do with notification sound ducking that could be causing the issue? Is there any other way to mute a notification with Xamarin.Android other than playing a blank sound? That is one route I think would be worth trying to fix this issue.
Here is the code I am using to generate notifications:
private static List<CustomNotification> _sentNotificationList = new List<CustomNotification>();
private static NotificationManagerCompat _notificationManager;
public async void SendNotifications(List<CustomNotification> notificationList)
{
await Task.Run(() =>
{
try
{
var _ctx = Android.App.Application.Context;
if (_notificationManager == null)
{
_notificationManager = Android.Support.V4.App.NotificationManagerCompat.From(_ctx);
}
if (notificationList.Count == 0)
{
return;
}
int notePos = 0;
foreach (var note in notificationList)
{
var resultIntent = new Intent(_ctx, typeof(MainActivity));
var valuesForActivity = new Bundle();
valuesForActivity.PutInt(MainActivity.COUNT_KEY, _count);
valuesForActivity.PutString("URL", note._noteLink);
resultIntent.PutExtras(valuesForActivity);
var resultPendingIntent = PendingIntent.GetActivity(_ctx, MainActivity.NOTIFICATION_ID, resultIntent, PendingIntentFlags.UpdateCurrent);
resultIntent.AddFlags(ActivityFlags.SingleTop);
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build();
//I am playing this blank sound to prevent android from spamming sounds as the notifications get sent out
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3");
//if the notification is the first in our batch then use this
//code block to send the notifications with sound
if (!_sentNotificationList.Contains(note) && notePos == 0)
{
var builder = new Android.Support.V4.App.NotificationCompat.Builder(_ctx, MainActivity.CHANNEL_ID + 1)
.SetAutoCancel(true)
.SetContentIntent(resultPendingIntent) // Start up this activity when the user clicks the intent.
.SetContentTitle(note._noteText) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.bitchute_notification2)
.SetContentText(note._noteType)
.SetPriority(NotificationCompat.PriorityMin);
MainActivity.NOTIFICATION_ID++;
_notificationManager.Notify(MainActivity.NOTIFICATION_ID, builder.Build());
_sentNotificationList.Add(note);
notePos++;
}
//if the notification isn't the first in our batch, then use this
//code block to send the notifications without sound
else if (!_sentNotificationList.Contains(note))
{
var builder = new Android.Support.V4.App.NotificationCompat.Builder(_ctx, MainActivity.CHANNEL_ID)
.SetAutoCancel(true) // Dismiss the notification from the notification area when the user clicks on it
.SetContentIntent(resultPendingIntent) // Start up this activity when the user clicks the intent.
.SetContentTitle(note._noteText) // Set the title
.SetNumber(1) // Display the count in the Content Info
.SetSmallIcon(Resource.Drawable.bitchute_notification2)
.SetContentText(note._noteType)
.SetPriority(NotificationCompat.PriorityHigh);
MainActivity.NOTIFICATION_ID++;
_notificationManager.Notify(MainActivity.NOTIFICATION_ID, builder.Build());
_sentNotificationList.Add(note);
notePos++;
}
ExtStickyService._notificationsHaveBeenSent = true;
}
}
catch
{
}
});
}
In my MainActivity I've created two different notification channels: one is silent; the other uses default notification setting for the device:
void CreateNotificationChannel()
{
var alarmAttributes = new Android.Media.AudioAttributes.Builder()
.SetContentType(Android.Media.AudioContentType.Sonification)
.SetUsage(Android.Media.AudioUsageKind.Notification).Build();
var uri = Android.Net.Uri.Parse("file:///Assets/blank.mp3");
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var name = "BitChute";
var description = "BitChute for Android";
var channelSilent = new Android.App.NotificationChannel(CHANNEL_ID, name + " Silent", Android.App.NotificationImportance.High)
{
Description = description
};
var channel = new Android.App.NotificationChannel(CHANNEL_ID + 1, name, Android.App.NotificationImportance.High)
{
Description = description
};
channel.LockscreenVisibility = NotificationVisibility.Private;
//here is where I set the sound for the silent channel... this could be the issue?
var notificationManager = (Android.App.NotificationManager)GetSystemService(NotificationService);
channelSilent.SetSound(uri, alarmAttributes);
notificationManager.CreateNotificationChannel(channel);
notificationManager.CreateNotificationChannel(channelSilent);
}
Full source: https://github.com/hexag0d/BitChute_Mobile_Android_BottomNav/tree/APILevel9
EDIT: something really interesting is that if I pulldown the system ui bar, the volume goes back to normal. Very strange workaround but it might help diagnose the cause.
DOUBLE EDIT: I used .SetSound(null, null) instead of using the blank .mp3 and the ducking works fine now. See comments
I'm having trouble with a AudioGraph in a UWP app. My trouble is that when I'm adding adding an Outgoing Connection to my input device node I get a Exception thrown with HRESULT: 0x88960001.
Using trial and error I figured out that the problem is with the MediaEncoding profile I set on both the input and output node... but I have now 2 settings only work on one machine and the other only works on another machine... I needed the audio to be Single Channel, 16bit sample with a 16K sample in PCM.
The code I'm using is fairly simple and was based on samples that exist online, the thing is it works only on some microphones and not others... I needed it to be generic and have always the same output so that I can input that to my service endpoint.
I left the 2 AudioEncodingProperties settings there (one of them commented out)
var result = await AudioGraph.CreateAsync(
new AudioGraphSettings(AudioRenderCategory.Media));
if (result.Status == AudioGraphCreationStatus.Success)
{
this.graph = result.Graph;
var microphone = await DeviceInformation.CreateFromIdAsync(
MediaDevice.GetDefaultAudioCaptureId(AudioDeviceRole.Default));
// Low gives us 1 channel, 16-bits per sample, 16K sample rate.
var outProfile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low);
//outProfile.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16);
outProfile.Audio = AudioEncodingProperties.CreatePcm(44100, 2, 32);
var inProfile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low);
//inProfile.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16);
inProfile.Audio = AudioEncodingProperties.CreatePcm(44100, 2, 32);
var outputResult = await this.graph.CreateFileOutputNodeAsync(file,
outProfile);
if (outputResult.Status == AudioFileNodeCreationStatus.Success)
{
this.outputNode = outputResult.FileOutputNode;
var inputResult = await this.graph.CreateDeviceInputNodeAsync(
MediaCategory.Speech,
inProfile.Audio,
microphone);
if (inputResult.Status == AudioDeviceNodeCreationStatus.Success)
{
//EXEPTION IS THROWN HERE
inputResult.DeviceInputNode.AddOutgoingConnection(
this.outputNode);
this.graph.Start();
}
}
}
else
{
throw new Exception("Could not create AudioGraph");
}
Thank you guys for our help
Instead of constructing the inputResult with the inProfile.Audio object, try using the default encoding properties for the graph:
var enc = graph.EncodingProperties;
CreateAudioDeviceInputNodeResult deviceInputNodeResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Media, enc, this.outputNode);
I had a similar issue and this cleared things up, and allowed the audio to be input from any device without specifying the encoding profile.
I have an application that is using an smart card reader for allowing the users to access parts of the system. On one location i have no issues. But another, which have an different type of card manufacturer has a lot of issues. It keeps getting an id of zero back. Then looking into the eventlog i saw this:
And this is the code:
card.Connect(reader, SHARE.Shared, PROTOCOL.T0orT1);
var apduGetID = new APDUCommand(0xFF, 0xCA, 0, 0, null, 4);
var apduRespGetID = card.Transmit(apduGetID);
long cardId = BitConverter.ToUInt32(apduRespGetID.Data.Reverse().ToArray(), 0);
the second problem is that then trying to debug the code, it works perfect, only then remove the breakpoint can i see the issue but not where. Can some one please help me?
P.S. i found this thread, but it does not work: https://superuser.com/questions/715688/smart-card-errors
Update: Here are the Transmit class
public override APDUResponse Transmit(APDUCommand ApduCmd)
{
var RecvLength = (uint)(ApduCmd.Le + APDUResponse.SW_LENGTH);
byte[] ApduBuffer;
var ApduResponse = new byte[ApduCmd.Le + APDUResponse.SW_LENGTH];
var ioRequest = new SCard_IO_Request
{
m_dwProtocol = m_nProtocol,
m_cbPciLength = 8
};
// Build the command APDU
if (ApduCmd.Data == null)
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)];
if (ApduCmd.Le != 0)
{
ApduBuffer[4] = ApduCmd.Le;
}
}
else
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
for (var nI = 0; nI < ApduCmd.Data.Length; nI++)
{
ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI];
}
ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
}
ApduBuffer[0] = ApduCmd.Class;
ApduBuffer[1] = ApduCmd.Ins;
ApduBuffer[2] = ApduCmd.P1;
ApduBuffer[3] = ApduCmd.P2;
m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out RecvLength);
if (m_nLastError != 0)
{
var msg = "SCardTransmit error: " + m_nLastError;
throw new SmartCardException(msg, m_nLastError);
}
var apduData = new byte[RecvLength];
for (var nI = 0; nI < RecvLength; nI++)
{
apduData[nI] = ApduResponse[nI];
}
return new APDUResponse(apduData);
}
Update 2: I have also tried with to put some Thread.Sleep()
Please check that on the second machine you have all the up-to-date drivers of the smart card. Also, sometimes it helps to replace the driver which is provided by the manufacturer with "Microsoft WUDF driver" - https://msdn.microsoft.com/en-us/library/windows/hardware/dn653571(v=vs.85).aspx
Please note, that you have two type of devices detected by the OS when you plug it in - the smart card enumerator device (smart card reader) and the smart card (sometimes called the smart card container) itself. One smart card reader can contain several smart cards.
Example of the smart card which driver was forcefully replaced with Microsoft WUDF to make the client application (iBank2) work:
The four smart card drivers have been forcefully replaced with basic Microsoft driver to make the application work.
Well if the other system does not take your smart card,just check the BIOS settings for smartcard.There is an option to disable/enable them in some systems.
I'm trying to upload large video files to youtube via the C# API using the ResumableUploader
The code looks like this:
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
settings.Timeout = int.MaxValue;
var newVideo = new Video();
newVideo.Title = title.Trim();
newVideo.Tags.Add(new MediaCategory("Games", YouTubeNameTable.CategorySchema));
newVideo.Keywords = keywords;
newVideo.Description = description;
newVideo.YouTubeEntry.Private = false;
newVideo.Tags.Add(new MediaCategory("StarCraft2, Replay", YouTubeNameTable.DeveloperTagSchema));
var contentType = MediaFileSource.GetContentTypeForFileName(filePathToUpload);
newVideo.YouTubeEntry.MediaSource = new MediaFileSource(filePathToUpload, contentType);
var link = new AtomLink("http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads");
link.Rel = ResumableUploader.CreateMediaRelation;
newVideo.YouTubeEntry.Links.Add(link);
var resumableUploader = new ResumableUploader(256); //chunksize 256 kilobyte
resumableUploader.AsyncOperationCompleted += resumableUploader_AsyncOperationCompleted;
resumableUploader.AsyncOperationProgress += resumableUploader_AsyncOperationProgress;
var youTubeAuthenticator = new ClientLoginAuthenticator(Configuration.YouTubeApplicationName, ServiceNames.YouTube, Configuration.YouTubeUsername, Configuration.YouTubePassword);
youTubeAuthenticator.DeveloperKey = Configuration.YouTubeApplicationKey;
resumableUploader.InsertAsync(youTubeAuthenticator, newVideo.YouTubeEntry, new object());
I try to get the video ID when the async opertion is finished like this:
private static void resumableUploader_AsyncOperationCompleted(object sender, AsyncOperationCompletedEventArgs e)
{
try
{
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
var request = new YouTubeRequest(settings);
Video v = request.ParseVideo(e.ResponseStream);
}
catch (Exception ex)
{
//Upload has been disturbed.
}
}
The problem is. Sometime there is a problem with the upload, shaky connection or stuff like that. When an error occurs AsyncOperationCompleted is getting called.
Now the question is. How do I resume the upload? I can get the current position via the AsyncOperationProgress event. But how do I proceed to continue the upload?
I know this is an old question but I found it while trying to do the same thing with V3 of the YouTube API. This looks like code from an earlier version of the API so my question asking the same thing for V3 of the API may help if you upgrade.
I've pasted some older code of mine if anyone is struggling with this but I'm switching to the new version and replacing all this code. The youtube_upload object is my own rolled class and not part of the api. I'm also using ReSharper now and following their naming conventions.
//Grab the rendered YouTube video ready for upload
string content_type = MediaFileSource.GetContentTypeForFileName(youtube_upload.YouTubeFileName);
MediaFileSource media_file_source = new MediaFileSource(youtube_upload.YouTubeFileName, content_type);
//Generate a media stream and move to the currently uploaded position within it
media_stream_resume = media_file_source.GetDataStream();
media_stream_resume.Seek(youtube_upload.CurrentPosition, SeekOrigin.Begin);
youtube_uploading_id = youtube_upload.YouTubeID;
//Attempt to resume the upload
resumable_uploader.ResumeAsync(youtube_authenticator, youtube_upload.ResumeUri,
youtube_upload.httpVerb, media_stream_resume, content_type, youtube_upload);
youtube_upload.ErrorText = Constants.YouTubeStatusResuming;
youtube_upload.SaveYouTube();
Alright. Actually i need mostly the mp4 format. But if it is possible to get for other types as well that would be nice. I just need to read the duration of the file. How can i do that with C# 4.0 ?
So the thing i need is like this video is like : 13 minutes 12 seconds
I can use 3 third party exes too. Like they save the information about the file to a text file. I can parse that text file.
Thank you.
This answer about P/Invoke for Shell32 reminded me of the Windows API Code Pack to access common Windows Vista/7/2008/2008R2 APIs.
It was very easy, using the PropertyEdit demo in the included samples, to figure out the Shell32 API to get various media file properties, like duration.
I assume the same prerequisite applies for having the proper demultiplexers installed, but it was quite simple, as it only required adding references to Microsoft.WindowsAPICodePack.dll and Microsoft.WindowsAPICodePack.Shell.dll and the following code:
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
using (ShellObject shell = ShellObject.FromParsingName(filePath))
{
// alternatively: shell.Properties.GetProperty("System.Media.Duration");
IShellProperty prop = shell.Properties.System.Media.Duration;
// Duration will be formatted as 00:44:08
string duration = prop.FormatForDisplay(PropertyDescriptionFormatOptions.None);
}
Other stuff
Some common properties for an MPEG-4/AAC audio media file:
System.Audio.Format = {00001610-0000-0010-8000-00AA00389B71}
System.Media.Duration = 00:44:08
System.Audio.EncodingBitrate = ?56kbps
System.Audio.SampleRate = ?32 kHz
System.Audio.SampleSize = ?16 bit
System.Audio.ChannelCount = 2 (stereo)
System.Audio.StreamNumber = 1
System.DRM.IsProtected = No
System.KindText = Music
System.Kind = Music
It's easy to iterate through all properties if you're looking for the available metadata:
using (ShellPropertyCollection properties = new ShellPropertyCollection(filePath))
{
foreach (IShellProperty prop in properties)
{
string value = (prop.ValueAsObject == null) ? "" : prop.FormatForDisplay(PropertyDescriptionFormatOptions.None);
Console.WriteLine("{0} = {1}", prop.CanonicalName, value);
}
}
You could also use windows media player, although it don't support alle file types you requested
using WMPLib;
public Double Duration(String file)
{
WindowsMediaPlayer wmp = new WindowsMediaPlayerClass();
IWMPMedia mediainfo = wmp.newMedia(file);
return mediainfo.duration;
}
}
You can use DirectShow API MediaDet object, through DirectShow.NET wrapper library. See Getting length of video for code sample, get_StreamLength gets you the duration in seconds. This assumes Windows has MPEG-4 demultiplexer installed (requires third party components with Windows prior to 7, I believe the same applies to another answer by cezor, there are free to redistribute components though).
IMHO you could use MediaInfo which gives you a lot of information about media files.
There is a CLI for it so you can use it from your code and get info you need.
You can take a look at this link.
I think you are looking for FFMPEG - https://ffmpeg.org/
there are also some free alternatives that you can read about them in this question - Using FFmpeg in .net?
FFMpeg.NET
FFMpeg-Sharp
FFLib.NET
you can see this link for examples of using FFMPEG and finding the duration - http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/
public VideoFile GetVideoInfo(string inputPath)
{
VideoFile vf = null;
try
{
vf = new VideoFile(inputPath);
}
catch (Exception ex)
{
throw ex;
}
GetVideoInfo(vf);
return vf;
}
public void GetVideoInfo(VideoFile input)
{
//set up the parameters for video info
string Params = string.Format("-i {0}", input.Path);
string output = RunProcess(Params);
input.RawInfo = output;
//get duration
Regex re = new Regex("[D|d]uration:.((\\d|:|\\.)*)");
Match m = re.Match(input.RawInfo);
if (m.Success)
{
string duration = m.Groups[1].Value;
string[] timepieces = duration.Split(new char[] { ':', '.' });
if (timepieces.Length == 4)
{
input.Duration = new TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3]));
}
}
}
FFMPEG project has a tool, called ffprobe which can provide you the information you need about your multimedia files and ouput the information in a nicely formated JSON.
Take a look at this answer for an example.
Using Windows Media Player Component also, we can get the duration of the video.
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.
I found the NReco.VideoInfo library to be the best option and far simpler than some of those above. It's a simple as giving the library a file path and it spits out the metadata:
var ffProbe = new FFProbe();
var videoInfo = ffProbe.GetMediaInfo(blob.Uri.AbsoluteUri);
return videoInfo.Duration.TotalMilliseconds;
I had the same problem and we built a wrapper for ffprobe Alturos.VideoInfo.
You can use it simply by installing the nuget package. Also the ffprobe binary is required.
PM> install-package Alturos.VideoInfo
Example
var videoFilePath = "myVideo.mp4";
var videoAnalyer = new VideoAnalyzer("ffprobe.exe");
var analyzeResult = videoAnalyer.GetVideoInfo(videoFilePath);
var duration = analyzeResult.VideoInfo.Format.Duration;
StreamReader errorreader;
string InterviewID = txtToolsInterviewID.Text;
Process ffmpeg = new Process();
ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.ErrorDialog = false;
ffmpeg.StartInfo.RedirectStandardError = true;
ffmpeg.StartInfo.FileName = Server.MapPath("ffmpeg.exe");
ffmpeg.StartInfo.Arguments = "-i " + Server.MapPath("videos") + "\\226.flv";
ffmpeg.Start();
errorreader = ffmpeg.StandardError;
ffmpeg.WaitForExit();
string result = errorreader.ReadToEnd();
string duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00.00").Length);