Maybe it is just late, but I ran into a dead end, hoping someone can help me out.
I have a very simple program which is supposed to work like this: The user can see a list of available streams. The user picks a stream to watch. After picking a stream I then want to launch VLC media player for them and play it.
I have everything in order except from one last thing - I don't know how to make the player play the stream. I assumed it would just be something like this:
System.Diagnostics.Process.Start(pathVLC, streams[choice]);
where
PathVLC is the path to the users player, for example C:\Programs\VLC\vlc.exe
streams is an array of strings, all on the form "http://somerandomstream.m3u8"
choice is the stream the user wanted to see.
While VLC opens successfully, nothing else happens, and I am completely lost on how to actually tell VLC to play the stream. What am I missing?
Edit: Looking at Vaughan Hilts answer I figured it out!
System.Diagnostics.Process VLC = new System.Diagnostics.Process();
VLC.StartInfo.FileName = pathVLC;
VLC.StartInfo.Arguments = "-vvv " + streams[choice];
VLC.Start();
You'll be required to start it up from the command line like so:
vlc -vvv http://www.example.org/your_file.mpg
This means you will need to pass in the -vvv flags as well in your array to succesfully start the stream.
I would start from inspecting supported command-line arguments e.g. here
Related
I have very little experience with DirectShow, so far I have managed paly a .wav file over a particular output device while being able to control its volume and get/set its track-position. Basically I’m able to create a very simple sound player application.
Here is the code I’m currently using:
//select an output device
DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory
DsDevice device = (DsDevice)devices[xxx];
//define a source
Guid iid = typeof(IBaseFilter).GUID;
object source = null;
device.Mon.BindToObject(null, null, ref iid, out source);
//build a basic graph to play the sound
IGraphBuilder player_gra = (IGraphBuilder)new FilterGraph();
player_gra.AddFilter((IBaseFilter)source, "Audio Render");
player_gra.RenderFile(#"test.wav", "");
//start the sound
(player_gra as IMediaControl).Run();
//control the volume
(player_gra as IBasicAudio).put_Volume(volume);
//get/set position on the track
(player_gra as IMediaPosition).get_Duration(out out1);//how long the track is
(player_gra as IMediaPosition).get_CurrentPosition(out out2);
(player_gra as IMediaPosition).put_CurrentPosition(yyy);
What I would like to do now is to play several .wav files simultaneously while being able to control the volume and track-position of each file at runtime.
My first attempt was to create several IGraphBuilder instances and run them at the same time but it seem that only one can play at the same time while the others wait until the currently playing one is terminated via:
Marshal.ReleaseComObject(player_gra);
My second attempt was to give the IGraphBuilder several Files to render before starting it.
…
player_gra.RenderFile(#"testA.wav", "");
player_gra.RenderFile(#"testB.wav", "");
player_gra.RenderFile(#"testC.wav", "");
…
This way the files are played simultaneously but I see no way to control the volume of each individual sound, much less its position on the audio track.
Thank you in advance ;-)
In these lines
DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.AudioRendererCategory);
DsDevice device = (DsDevice)devices[0];
you enumerate audio output devices and pick the first "random" device which appears to be Default WaveOut Device or one of its instances.
It has a legacy behavior that only one active instance is actually sending data to playback. There is no fundamental limitation in the system to prevent from simultaneous plyback, it is just legacy behavior.
That is, you have both graph playing but audio from the second is muted.
Audio mixing is disabled in the waveOut Audio Renderer, so if you need to mix multiple audio streams during playback, use the DirectSound renderer.
If you use Default DirectSound Device instead (which you can quickly pick up by using different index in device[NNN] in code) you'll hear what you expect to hear.
DirectShow.NET does the enumeration somehow confusingly, Default DirectSound Device normally has highest merit and is listed first and you seem to be given devices in different order.
for a new project, I used the Windows Media Player component. It should play a Livestream and this works fine for me, but after 10s the stream loads again and begins at 0 seconds (just like a 10s video clip).
There are two solutions I can see, but I don't know a way for them. The code itself is pretty simple.
private void tbutton_Click(object sender, EventArgs e)
{
tvplayer.currentPlaylist.name = "TV-Stream";
tvplayer.URL = (stream-url);
}
The first would be to "let the player know" that the video source is a stream and not a video, but I don't know how I should do that.
The second solution would be to modify the duration of the "video", the Media Player plays to... maybe two hours or 24 hours. I know this is somehow possible as I read about it in the Metafile Elements Reference (https://msdn.microsoft.com/de-de/library/windows/desktop/dd564668(v=vs.85).aspx), anyway, I don't see how.
Can someone give me a hint how I could do that?
I tried both HLS and HDS versions of the livestream, there is no difference. The problem is the same. The stream itself has a H.264 MP4-format.
I guess the problem is that the livestream is loaded in 10s-segments.
I'm making a sampler program where each key from 1 to 9 will make a different sound.
Everything works fine, but when I press two (or more) sounds at the same time, the second one "kills" the first one.
I'm playing the sounds from .WAV files, using SoundPlayer. How can I solve this?
You'll need to use DirectX (DirectSound) or some similar API that is designed to allow the playing of multiple sounds at the same time.
There is one simple way to play multiple sounds at once in C# or VB.Net. You will have to call the mciSendString() API Function to play each .wav file. You won't even have to do multi-threading, unless you are loop-playing. Here is a complete working example of a MusicPlayer class created using mciSendString().
// Sound api functions
[DllImport("winmm.dll")]
static extern Int32 mciSendString(string command, StringBuilder buffer, int bufferSize, IntPtr hwndCallback);
In the above function, the key is first parameter command. As long as you call two functions with a separate command name, they will play separately/simultaneously. This is what I did in one of my C# programs:
private void PlayWorker()
{
StringBuilder sb = new StringBuilder();
mciSendString("open \"" + FileName + "\" alias " + this.TrackName, sb, 0, IntPtr.Zero);
mciSendString("play " + this.TrackName, sb, 0, IntPtr.Zero);
IsBeingPlayed = true;
}
EDIT: Added link to a working example.
You could do this:
SoundPlayer supports WAV Stream. You could
MIX samples you play 'by-hand' and,
Fake (get the WAV header from somewhere, it's not complicated).
And provide such stream as a parameter to the SoundPlayer constructor.
That way you won't have to use somehow complicated DirectSound libraries, and still have mixing (multiple sounds at once).
using System.Windows.Media
Function void Play(string audioPath)
{
MediaPlayer myPlayer = new MediaPlayer();
myPlayer.Open(new System.Uri(audioPath));
myPlayer.Play();
}
Play(Application.StartupPath + "\\Track1.wav");
Play(Application.StartupPath + "\\Track2.wav");
This code could play two audio files simultaneously, the call in second audio track2.wav will not disturb the play of track1.wav .
I'm guessing that in your KeyPress event (or whatever you're using) you're creating a new instance of SoundPlayer using the constructor that takes a path to the WAV file, and then calling its Play method. In theory this shouldn't cause the "mono" effect that you're encountering, since Windows has been capable of playing multiple WAV files simultaneously since Windows 98. What I think you're hearing (based on my own use of this class) is not a cutoff of the first sound when the second starts, but actually a glitch that results from overall playback pausing as the WAV file is loaded from disk.
Instead of loading up a new instance of SoundPlayer on each key press, try creating an array of class-scoped SoundPlayer objects and pre-loading them from disk in your form's Load event. Then just call each SoundPlayer's Play method when the key is pressed. This may fix your problem, although I think you will still get occasional glitches this way.
you need to use xAudio2 via SharpDX , it is a directX component dedicated for game development , you can find a full working sample here:
https://github.com/sharpdx/SharpDX-Samples/tree/master/Desktop/XAudio2/PlaySound
Currently, I have a feature on an ASP.NET website where the user can play back MP3 Files. The code looks something like this:
Response.Clear();
Response.ContentType = "audio/mpeg";
foreach (DataChunk leChunk in db.Mp3Files.First(mp3 => mp3.Mp3ResourceId.Equals(id)).Data.Chunks.OrderBy(chunk => chunk.ChunkOrder))
{
Response.BinaryWrite(leChunk.Data);
}
Unfortunately, if a larger MP3 file is selected, the audio does not begin to play until the entire file is downloaded, which can cause a noticeable delay. Is there any way to get the MP3 to start playing immediately, even though the entire file may not yet be transferred?
You should be able to do what you want by writing to the outpstream of the response, i.e.:
Response.OutputStream.Write
It is also probably a good idea to check previously if Response.IsClientConnected and give up if not.
I found a demo that allows playback of mp3 files from an asp.net web application:
http://aspsnippets.com/Articles/Save-MP3-Audio-Files-to-database-and-display-in-ASPNet-GridView-with-Play-and-Download-option.aspx
try this:
Response.BufferOutput = false; //sets chunked encoding
Response.ContentType = "audio/mpeg";
using (var bw = new BinaryWriter(Response.OutputStream))
{
foreach (DataChunk leChunk in db.Mp3Files.First(mp3 => mp3.Mp3ResourceId.Equals(id)).Data.Chunks.OrderBy(chunk => chunk.ChunkOrder))
{
if (Response.IsClientConnected) //avoids the host closed the connection exception
{
bw.Write(leChunk.Data);
}
}
}
Also, go yo your web.config file and do this if you still have problems with chunked encoding:
<system.webServer>
<asp enableChunkedEncoding="true" />
</system.webServer>
The error you reported above about the host being closing the connection is happening probably because you are opening the page using the browser and when the browser reads the content type, it opens the media player and closes itself who had the opened connection which was then closed, causing that error, so to avoid this, you need to check periodically whether your client is still connected or not.
Finally, I would use a Generic Handler (.ashx) or a custom handler and set a .mp3 extension for this if you are using a aspx page to avoid the unnecessary overhead of the web page.
I hope this helps.
Try setting Response.BufferOutput = false before streaming the response.
If the location of the MP3 files are publicly available to your user then an alternative approach could be to just return the MP3's URL and use the HTML 5 audio tags in your mark up to stream the music. I am pretty sure that the default behaviour of the audio tag would be to stream the file rather than wait until the whole file has downloaded.
One method to support this would be implementing HTTP byte range requests.
By default I don't believe that ASP.NET does this, and definitely won't if using any of the code in the questions or the answer.
You can implement this manually with a little work though. Another option, which would be much less dev work, would be to let IIS serve a static file. I assume that isn't an option though.
Here's an example implementation:
http://www.codeproject.com/Articles/820146/HTTP-Partial-Content-In-ASP-NET-Web-API-Video
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