I am using Vlc.DotNet.Forms package in my project. I open one video on form. Everything okay. But If I want to open a video again. When I change the volume, the volume of both videos changes.
My Code Example:
public VlcControl control;
public void Player(string url,int volume){
this.control = new VlcControl();
var currentAssembly = Assembly.GetEntryAssembly();
var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
var libDirectory = new DirectoryInfo(Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
control.BeginInit();
control.VlcLibDirectory = libDirectory;
control.Dock = DockStyle.Fill;
control.EndInit();
this.Controls.Add(control);
control.SetMedia(new Uri(#"" + url + ""));
control.Audio.Volume=volume;
control.Play();
}
For example,
Player("C:\\test\video1.mp4",50);
Player("C:\\test\video2.mp4",75);
The first video opens and the volume becomes 50. Then when I open the second video, the volume of both videos is 75.
I use these packages
VideoLAN.LibVLC.Windows (Version 3.0.0) https://www.nuget.org/packages/VideoLAN.LibVLC.Windows
Vlc.DotNet.Forms (Version 3.0.0) https://github.com/ZeBobo5
It seems that the previous answer did not work for me, instead I used the following:
vlcControl.Play();
var directsound = vlcControl.Audio.Outputs.All.FirstOrDefault(x => x.Name == "directsound");
if (directsound != null)
{
vlcControl.Audio.Outputs.Current = directsound;
vlcControl.Audio.IsMute = true;
}
Setting the directsound just after having started the player.
You can then toggle mute with:
vlcControl.Audio.ToggleMute();
Setting the volume is similar with:
vlcControl.Audio.Volume = 50;
This seems to be a known issue of libvlc 3.x.
The workaround is to use a different audio output. In Vlc.DotNet, you can do so like this:
control.VlcMediaplayerOptions = new []{ "--aout=directsound" };
Before control.EndInit();.
References:
https://forum.videolan.org/viewtopic.php?t=147229
https://github.com/ZeBobo5/Vlc.DotNet/issues/524
Related
I'm trying to play the built-in webcam feed in a MediaElement within a UWP app. It works fine for a few users but there is no feed played for most and I'm lost on what could be the issue.
Some observations when the webcam feed doesn't play:
The code executes without any exceptions
The dialog that requests user permission to access the camera is shown
The LED indicating the webcam is in use turns on soon as it is executed, but there is no feed.
Skype and Camera apps work fine.
The app was working as expected until a week back. A few things that changed in the mean time that could have had an impact are
Installed Kaspersky
A bunch of windows updates
Uninstalled VS2017 professional edition & VS2019 Community edition and installed VS2019 Professional Edition
Some additional information that might be needed to narrow down the reason.
Webcam is enabled in the Package manifest of the app
App Target version: 18362
App Min version: 18362
Windows OS Version : 18362
Any help on this would be highly appreciated. Thanks much in advance!
Here is the piece of code used to play the webcam feed where VideoStreamer is a MediaElement.
private async Task PlayLiveVideo()
{
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
var eligibleGroups = allGroups.Select(g => new
{
Group = g,
// For each source kind, find the source which offers that kind of media frame,
// or null if there is no such source.
SourceInfos = new MediaFrameSourceInfo[]
{
g.SourceInfos.FirstOrDefault(info => info.DeviceInformation?.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front
&& info.SourceKind == MediaFrameSourceKind.Color),
g.SourceInfos.FirstOrDefault(info => info.DeviceInformation?.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back
&& info.SourceKind == MediaFrameSourceKind.Color)
}
}).Where(g => g.SourceInfos.Any(info => info != null)).ToList();
if (eligibleGroups.Count == 0)
{
System.Diagnostics.Debug.WriteLine("No source group with front and back-facing camera found.");
return;
}
var selectedGroupIndex = 0; // Select the first eligible group
MediaFrameSourceGroup selectedGroup = eligibleGroups[selectedGroupIndex].Group;
MediaFrameSourceInfo frontSourceInfo = selectedGroup.SourceInfos[0];
MediaCapture mediaCapture = new MediaCapture();
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings()
{
SourceGroup = selectedGroup,
SharingMode = MediaCaptureSharingMode.ExclusiveControl,
MemoryPreference = MediaCaptureMemoryPreference.Cpu,
StreamingCaptureMode = StreamingCaptureMode.Video,
};
try
{
await mediaCapture.InitializeAsync(settings);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("MediaCapture initialization failed: " + ex.Message);
return;
}
var frameMediaSource1 = MediaSource.CreateFromMediaFrameSource(mediaCapture.FrameSources[frontSourceInfo.Id]);
VideoStreamer.SetPlaybackSource(frameMediaSource1);
VideoStreamer.Play();
}
As mentioned by Faywang-MSFT here , it worked after marking the application as trusted in Kaspersky.
My issue is quite simple.
I want to turn the flash On (and keep it On) on a Windows 10 universal app project but nothing I try works.
This is the code
MediaCapture MyMediaCapture = new MediaCapture();
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
DeviceInformation cameraDevice =
allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null &&
x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
cameraDevice = cameraDevice ?? allVideoDevices.FirstOrDefault();
if (cameraDevice == null)
{
Debug.WriteLine("No camera device found!");
}
else
{
await MyMediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
{
VideoDeviceId = cameraDevice.Id
});
var MyVideoDeviceController = MyMediaCapture.VideoDeviceController;
var MyTorch = MyVideoDeviceController.TorchControl;
if (MyTorch.Supported)
{
var captureElement = new CaptureElement();
captureElement.Source = MyMediaCapture;
await MyMediaCapture.StartPreviewAsync();
FileStream tmp = new FileStream(System.IO.Path.GetTempFileName() + Guid.NewGuid().ToString() + ".mp4", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, 10000, FileOptions.RandomAccess | FileOptions.DeleteOnClose);
var videoFile = await KnownFolders.VideosLibrary.CreateFileAsync(tmp.Name, CreationCollisionOption.GenerateUniqueName);
var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Wvga);
await MyMediaCapture.StartRecordToStorageFileAsync(encodingProfile, videoFile);
MyTorch.PowerPercent = 100;
MyTorch.Enabled = true;
}
}
Edit: add code
It looks like you're trying to use an old method of accessing the flashlight which we no longer have to use in Windows 10 UWP development. Take a look at the new Lamp feature in Windows.Devices.Lights in this sample on GitHub.
It's a great starting point for using the flash independent of access the camera APIs.
You're on the right path. Depending on the device (because of driver-specific implementations), you'll have to start the preview or maybe even start a video recording session for the light to turn on.
Because of that, and to guarantee compatibility with most devices, I'd recommend you actually do both.
I'm using VlcDotNet to stream video and I faced a strange issue recently. When I stream video from my webcamera with VLC player I can perfectly watch it. But when I try to stream it using VlcControl I get an error that VLC couldn't connect to the source. I'm using the same options in VLC and VlcControl:
:sout=#transcode{vcodec=h264,vb=0,scale=0,acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=ffmpeg{mux=flv},dst=:10177/} :sout-keep
Maybe I missing something, please look at my code:
if (Environment.Is64BitOperatingSystem)
{
VlcContext.LibVlcDllsPath = CommonStrings.LIBVLC_DLLS_PATH_DEFAULT_VALUE_AMD64;
VlcContext.LibVlcPluginsPath = CommonStrings.PLUGINS_PATH_DEFAULT_VALUE_AMD64;
}
else
{
VlcContext.LibVlcDllsPath = CommonStrings.LIBVLC_DLLS_PATH_DEFAULT_VALUE_X86;
VlcContext.LibVlcPluginsPath = CommonStrings.PLUGINS_PATH_DEFAULT_VALUE_X86;
}
//Set the startup options
VlcContext.StartupOptions.IgnoreConfig = true;
VlcContext.StartupOptions.LogOptions.LogInFile = true;
VlcContext.StartupOptions.LogOptions.ShowLoggerConsole = false;
VlcContext.StartupOptions.LogOptions.Verbosity = VlcLogVerbosities.None;
VlcContext.CloseAll();
VlcContext.Initialize();
VlcControl player = new VlcControl();
var media = new LocationMedia("dshow://");
media.AddOption(":sout=#transcode{vcodec=h264,vb=0,scale=0,acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=ffmpeg{mux=flv},dst=:10177/} :sout-keep");
player.Media = media;
player.Play();
Console.WriteLine("Translation started...");
Console.ReadLine();
I think Vlc could not connect to your webcam because you didn't pass it the name of the camera
i tried it and i got
:dshow-vdev=USB2.0 Camera :dshow-adev= :live-caching=300
try at as another aption but make sure to change the camera name
PS. you can find this option, when you open Open Capture device --> tick the Show More Options
i think this will solve your problem :)
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);
For the last 2 years, I'm using the next code to init an audio recorder object, and everything has been fine.
ar = AVAudioRecorder.ToUrl(url, settings, out errorRecorder);
ar.MeteringEnabled = false;
However, this week I made an upgrade to: Mono 2.10.2, MonoTouch 4.0.1.10285, MonoDevelop 2.4.2. I'm still using Xcode 3.2.6 and iOS SDK 4.3. With this configuration, the method
AVAudioRecorder.ToUrl(url, settings, out errorRecorder)
always returned a null value to the ar object.
Somebody has the same problem? This is the complete code:
NSError errorRecorder;
NSUrl url;
NSDictionary settings;
AVAudioRecorder ar;
string path, audioFile;
NSObject[] values = new NSObject[]
{
NSNumber.FromInt32((int)AudioFileType.M4A),
NSNumber.FromFloat(11025.0f),
NSNumber.FromInt32(1),
NSNumber.FromInt32((int)AVAudioQuality.Min)
};
NSObject[] keys = new NSObject[]
{
AVAudioSettings.AVFormatKey,
AVAudioSettings.AVSampleRateKey,
AVAudioSettings.AVNumberOfChannelsKey,
AVAudioSettings.AVEncoderAudioQualityKey
};
settings = NSDictionary.FromObjectsAndKeys (values, keys);
path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
path = Path.Combine(path, audioDir);
if (!Directory.Exists(path)){
Directory.CreateDirectory(path);
}
audioFile = newJobEntity.jobid + "_" + numFiles + ".caf";
if (!File.Exists(Path.Combine(path, audioFile)))
FileStream audioFileStream = File.Create(Path.Combine(path, audioFile));
url = NSUrl.FromFilename(Path.Combine(path, audioFile));
ar = AVAudioRecorder.ToUrl(url, settings, out errorRecorder);
ar.MeteringEnabled = false;
Thanks in advanced.
The change happened in the settings object. If you read apples documentation it matches the examples. This should do it for you.
Change: AudioFileType.M4A
To: AudioFormatType.M4A
And
Change: AVAudioSettings.AVFormatKey
To: AVAudioSettings.AVFormatIDKey