WPF MediaElement, change audio track - wpf

I'm writing a Media Player using WPF and the MediaElement.
I was playing a video i have that has several audio tracks. But they are both playing at the same time :(
How do i just play one of them ? is it at all possible ?

I think this problem is in the audio and video DirectShow codecs you use. Can you play the video correct in the Windows Media Player? If no, please re-install the appropriated codecs.
Some months ago I have completely prototyped the requirements to switch audio tracks in order to show the video-help in our multi-language software.
My experience shows some alternatives:
Use the WMP-control via WinForms host, and then change the language like:
var control = ((IWMPControls3)wmpControl.Ctlcontrols);
control.currentAudioLanguage = 9; // english
The Complete list of the LCID you can find here.
To list all audio tracks in the video you can use something like:
wmpControl.PlayStateChange += (o, args) => {
if(args.newState == 3) {
var control = ((IWMPControls3)wmpControl.Ctlcontrols);
for(int i = 1; i <= control.audioLanguageCount; i++) {
MessageBox.Show(control.getAudioLanguageID(i) + ": " + control.getAudioLanguageDescription(i));
}
}
};
Use the separate audio tracks and play it synchronously to the video using the MediaPlayer. The main problem of this method is, that you must synchronize audio and video playback, start, stop, seeking,.. manually.
I hope this helps you to choose your solution.

It is not possible with the WPF MediaElement. If you have some DirectShow know-how, you can try my WPF MediaKit and either modify the MediaUriElement/Player or create your own.

Related

Streaming Live audio using Codename One

I am trying to convince a friend of mine to use CN1 as his dev platform for mobile apps. One of the challenges he has brought up is the ability to stream live audio from a radio station using a CN1 app.
I have had a look at the docs and I can see examples of loading media files that are already on the phone, but I cannot see an example of where you point it at a URL and stream live audio.
As you have probably guessed he is interested in developing radio apps for remote radio stations that don't already have their own
Is it possible to do this in CN1?
That's quite possible with CN1 and number of developers have done that in the past.
You can use MediaManager and point it to your remote streaming URL.
Below works for playing an audio file from remote URL and could work for streaming:
Form radio = new Form(new BorderLayout());
Display.getInstance().scheduleBackgroundTask(() -> {
try {
Media audio = MediaManager.createMedia(streamingUrl, false);
audio.prepare();
Display.getInstance().callSerially(() -> {
final MediaPlayer player = new MediaPlayer(audio);
player.setAutoplay(true);
audio.setNativePlayerMode(false);
radio.add(BorderLayout.CENTER, player);
radio.revalidate();
});
} catch (IOException err) {
Log.e(err);
ToastBar.showErrorMessage("Error streaming audio: " + err);
}
});
radio.show();
To avoid this error "Video Playing is not supported on this platform", you have to put true to isVidio parameter like this when handling video stream.
Media audio = MediaManager.createMedia(streamingUrl, true);

Stream YouTube video from extracted url

I am trying to find solution to play YouTube video from http stream. Not as embedded player or via website. The reason of that as I need to play some clips locally in app that prevented to be embedded.
So the first task to obtain http stream is easy to solve, e.g. using YouTubeExtractor. For example from this youtube url
https://www.youtube.com/watch?v=31crA53Dgu0
YouTubeExtractor extracts such url for downloading video. As you can see there is no piece of path to concrete .mp4 or .mov file. There is also binding to IP, so the url won't work on your side.
https://r3---sn-puu8-3c2e.googlevideo.com:443/videoplayback?sparams=dur,gcr,id,initcwndbps,ip,ipbits,itag,lmt,mime,mm,mn,ms,mv,pl,ratebypass,requiressl,source,upn,expire&source=youtube&initcwndbps=3147500&pl=19&upn=oYYkSNBwoc8&fexp=9412913,9416126,9416891,9422596,9428398,9429016,9431012,9431364,9431901,9432206,9432825,9433096,9433424,9433623,9433946,9434085,9435504,9435703,9435937&id=o-AGanAaajMgOmp4VrXIwo9jewJnqlsvZecDxCcRpSN3lS&expire=1462821352&gcr=ua&ip=12.34.56.149&lmt=1458705532562546&ms=au&mt=1462799507&mv=m&dur=217.849&sver=3&itag=22&key=yt6&mn=sn-puu8-3c2e&mm=31&ipbits=0&mime=video/mp4&ratebypass=yes&requiressl=yes&signature=A142619EBA90D00CC46FF05B9CF1E3469B0EF196.072B532670A4D833582F94CF9C46F1F7D298F230&fallback_host=tc.v1.cache5.googlevideo.com
private string ExtractVideoUrl(string youtubeUrl)
{
IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(youtubeUrl, false);
var video = videoInfos.First();
if (video.RequiresDecryption)
{
DownloadUrlResolver.DecryptDownloadUrl(video);
}
return video.DownloadUrl; // videoInfos.First().DownloadUrl;
}
Then to download video this lib uses the code below. The interesting moment is in reading stream and writing to file the contents of youtube video.
var request = (HttpWebRequest)WebRequest.Create(this.Video.DownloadUrl);
if (this.BytesToDownload.HasValue)
{
request.AddRange(0, this.BytesToDownload.Value - 1);
}
// the following code is alternative, you may implement the function after your needs
using (WebResponse response = request.GetResponse())
{
using (Stream source = response.GetResponseStream())
{
**// HOW to Play source stream???**
using (FileStream target = File.Open(this.SavePath, FileMode.Create, FileAccess.Write))
{
var buffer = new byte[1024];
bool cancel = false;
int bytes;
int copiedBytes = 0;
while (!cancel && (bytes = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, bytes);
....
So the general question is how to play video from that open stream? For example Chrome, Firefox and KMPlayer are doing this easily. The browsers generate a simple page with video tag, so it will be trivial to manage the player through JS. But...internal WebBrowser control can't, it suggests to download file. I tried CEFSharp (Chrome Embeded Framework) and no luck there. Maybe anybody know good video player WPF library which can streaming video? I also tried VLC.wpf and Shockwave Flash, but still unhappy with this extracted url. A lot of searching but results insufficient for now.
After 2 days researching I found the solution of how to play youtube video url directly from WPF application.
Some notes before:
WebBrowser component for WPF and the same for WinForms does not support HTML5. So no way to play video using <video> tag there
Chrome Embeded Framework (CEF)and its CEFSharp wrapper does not support <audio> and <video> tags by default. As I found on SO it is needed to recompile CEF to support audio and it seems video too. --enable-multimedia-streams option didn't work on my side at all to play video
WPF MediaElement component does not support playing video from streams. However there are workaroung exists, they are unsuitable to play youtube url's.
No .NET media player found which could play video from Stream object returned by HttpWebRequest
So the solution is in using GeckoFx webbrowser which is also available via nuget. As it is WinForms based component it is needed to use WinFormsHosting to use it in WPF. Final solution is:
<xmlns:gecko="clr-namespace:Gecko;assembly=Geckofx-Winforms">
....
<WindowsFormsHost Width="400" Height="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<gecko:GeckoWebBrowser x:Name="_geckoBrowser"/>
</WindowsFormsHost>
And simple code to use:
public void PlayVideo(string videoId)
{
var url = string.Format("https://www.youtube.com/watch?v={0}", videoId);
var videoUrl = ExtractVideoUrl(url);
_geckoBrowser.Navigate(videoUrl);
}
GeckoFx is depeneded on XulRunner runtime sdk. It is installed with nuget package though. One cons in this solution is the size of all app dependencies increased for over +70mb.

Silverlight MP3 Playing Library

I'm trying to play MP3 files in SilverSprite, and it's super buggy. Is there an alternative library I can use to play MP3s in Silverlight?
Edit: Now that there's a bounty, I'm specifically looking for something that:
Works with SL 3-4
Is a separate project/DLL
Will work in SilverSprite projects (I'm using a layer on top of SS) -- no GUI, just methods I can call to play sounds
Works with content that has the build action set to Content. I cannot use embedded resources due to a bug in SilverSprite. My app will not run.
Plays MP3s.
Can play multiple audio files at the same time
I hope it's clear what I'm trying to find. I would like something I can embed in my own game engine, which sits on top of SilverSprite. I will supply all the audio files in the XAP. (The SilverSprite audio is quite broken and doesn't work.)
Update: The specific direction I would probably like to go in is to instantiate a new MediaElement, set the source, and play it. I have some code below, but a) NaturalDuration.TimeSpan.TotalMilliseconds reports 0, and b) the .MediaOpened never triggers.
MediaElement m = new MediaElement();
m.Source = new Uri("Content/Audio/chimes.mp3", UriKind.Relative);
m.Stop(); // useless?
//m.SetSource(new FileStream("Content/Audio/chimes.mp3", FileMode.Open)); // "Permission denied" exception, is it even finding the file?
m.Volume = 1; // Max
m.Position = TimeSpan.FromMilliseconds(0);
while (m.CurrentState != System.Windows.Media.MediaElementState.Closed)
{
Thread.Sleep(10);
}
m.MediaOpened += (sender, e) =>
{
m.Play();
};
m.Play();
For some working code rather similar to your updated approach see http://www.wiredprairie.us/blog/index.php/archives/577 . Beware that the MediaElement needs to be added to the control/component tree - see http://www.michaelsnow.com/2010/12/17/playing-sound-effects-on-windows-phone-7/.
Two very interesting options for your requirements is this library and this one.
For this kind of stuff you could also implement/use a custom MediaStreamSource like this one... see here and here.
EDIT - some other options:
Playing multiple sounds in parallel via XNA see source code at http://create.msdn.com/en-US/education/catalog/sample/silverlightsound
Using MediaPlayer class from XNA 4 for example:
MediaPlayer.Stop();
MediaPlayer.Volume = 1;
MediaPlayer.Play(Song.FromUri("TestSound", new Uri("/Content/Audio/chimes.mp3", UriKind.Relative)));
As for playing multiple sound files at the same time:
IIRC this is something which could cause your app to fail validation.

play beep in silverlight

I am trying to make a small application for learning Morse code and I am stuck because I do not know how to play a Beep in Silverlight.
How can I do something like?
Console.Beep(Freq, elementLength)
(I have made a console application that uses Console.Beep and it does not work very well (for 20word per minute the dot length is 60ms and the space between 2 signs is 180ms so for letter s witch is ... (3 dots) in my headphones I hear poc! not a clear sound)... I suppose the solution is to use DirectX/XNA)
Can you please advise me how to make the application beep and if xna is the solution can you please direct me to a tutorial (I did not figure out what sdk I need to install and from where to download)
Thank you
There is no direct "beep" in silverlight, that I'm aware. However, you have a plethora of sound capabilities; one of which is using the MediaElement control. So, you could add one of those to your page:
<MediaElement x:Name="beeper"></MediaElement>
Then in your code behind you can assign and call the sound:
private void AssignBeep()
{
Uri beepUri = new Uri("Project;component/beep.mp3", UriKind.RelativeOrAbsolute);
StreamResourceInfo streamInfo = Application.GetResourceStream(beepUri);
this.beeper.SetSource(streamInfo.Stream);
this.beeper.AutoPlay = false;
}
Then you can call it for a beep:
private void PlayBeep()
{
this.beeper.Position = new TimeSpan(0,0,0,0);
this.beeper.Volume = 1;
this.beeper.Play();
}
Credits to forums.silverlight.net
Look at this.. i think this is what you need..
http://silversynth.codeplex.com/

YouTube on Windows Phone with MediaElement

This blog post suggests that it might be possible to play YouTube videos with the Silverlight MediaEelement directly.
<MediaElement HorizontalAlignment="Left"
VerticalAlignment="Top"
Source="http://www.youtube.com/get_video?
video_id=8yuIw_0ejLs&t=vjVQa1PpcFPrX3tFoahhu4DbniDIqTLkwybdm8xuCt8%3D&fmt=22"/>
I was wondering if this holds true for the Windows Phone 7. I have an application that is based on playing videos hosted on YouTube, and it would be nice to be able to have more control over the video experience other than just launching the browser with the YouTube video URL.
Unless you have a direct link to video content, you cannot display YouTube videos on Windows Phone 7. As far as I know, get_video is no longer available for public access.
Quoting from the Windows Phone Developer FAQ
How can I play youtube videos in my app?
Use the WebBrowserTask and open the target URL in the browser; if the youtube app is installed, it will play, if not installed, it will prompt the user to install and then play.
For everyone else still curious the problem to overcome is getting a direct link to the video which does require a small hack but it's very reliable and easy to do. Firstly you need the video id so you can get the youtube url which you can use the youtube api for. Then do something like this. I pretty much converted a userscript to silverlight.
WebClient client = new WebClient();
string url = "http://www.youtube.com/watch?v=HLQqOpILDcI";
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ClientDownloadStringCompleted);
client.DownloadStringAsync(new Uri(url, UriKind.Absolute));
the next bit looks bad.
private void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
rx = new Regex("(?<=url_encoded_fmt_stream_map=)([^(\\\\)]*)(?=\\\\)", RegexOptions.IgnoreCase);
match = rx.Matches(flashvars);
string video_format = match[0].ToString();
string sep1="%2C";
string sep2="%26";
string sep3="%3D";
string link = "";
string[] videoFormatsGroup = Regex.Split(video_format, sep1);
for (var i=0;i<videoFormatsGroup.Length;i++){
string[] videoFormatsElem = Regex.Split(videoFormatsGroup[i], sep2);
if (videoFormatsElem.Length<5) continue;
string[] partialResult1 = Regex.Split(videoFormatsElem[0], sep3);
if (partialResult1.Length<2) continue;
string url = partialResult1[1];
url = HttpUtility.UrlDecode(HttpUtility.UrlDecode(url));
string[] partialResult2 = Regex.Split(videoFormatsElem[4], sep3);
if (partialResult2.Length<2) continue;
int itag = Convert.ToInt32(partialResult2[1]);
if (itag == 18){
link = url;
}
}
}
the last bit itag==18 selects the quality according to this
{'5':'FLV 240p','18':'MP4 360p','22':'MP4 720p (HD)','34':'FLV 360p','35':'FLV 480p','37':'MP4 1080p (HD)','38':'MP4 4K (HD)','43':'WebM 360p','44':'WebM 480p','45':'WebM 720p (HD)','46':'WebM 1080p (HD)'};
now you can do whatever you want with the link like open it with mediaplayerlauncher or mediaelement. personally i'd love to download it to isolated storage and play it at the same time but at the moment that seems easier said than done. thanks for your time sorry for the long post.
I am sure you can adjust it for Windows Phone http://www.codeproject.com/KB/WPF/YouViewer.aspx

Resources