Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[Tutorial] Audio- und Videowiedergabe mit MCI
maxE
myCSharp.de - Member



Dabei seit:
Beiträge: 456
Herkunft: Sachsen

Themenstarter:

[Tutorial] Audio- und Videowiedergabe mit MCI

beantworten | zitieren | melden

Audio- und Videowiedergabe mit MCI

Einleitung

Da immer wieder die Frage auftaucht, wie man denn MP3s, WMAs, Videos und CDs am einfachsten abspielen kann, habe ich mich entschlossen diesen Artikel zu schreiben.
Windows bietet ein sehr leistungsfähiges Interface zur Wiedergabe von digitalen Medien.
Diese Library ist bei jeder Windowsinstallation vorhanden.

Benötigte DLL-Importe

Um die gesamte Schnittstelle anzusprechen, brauch man nur eine C-Funktion, die wir mit Hilfe von DllImport einbinden:


[DllImport("winmm.dll")]
private static extern int mciSendString(string cmd, StringBuilder ret, int retLen, IntPtr hwnd);

Parameter:
  • cmd : Kommandostring, welches an den MCI Treiber übergeben wird (Dazu später mehr).
  • ret: Enthält Rückgabewert des ausgeführten Kommandos. Vor allem für Statusabfragen wichtig.
  • retLen: Länge des Rückgabewertes.
  • hwnd: Fensterhandle. Einige Kommandos erzeugen Events für die Windows-Nachrichtenschleife, wenn ein notify-Flag an das Kommando gehängt wird. Man kann sich zum Beispiel benachrichtigen lassen, wenn ein Mp3-Stream beendet wurde.

Nun gut, ich habe etwas gelogen
Wir werden für die Fehlerbehandlung noch eine 2. Funktion benötigen:


[DllImport("winmm.dll")]
private static extern int mciGetErrorString(int errCode, StringBuilder errText, int errLen);

Diese gibt uns lokalisierte Fehlertexte für einen bestimmten Fehlercode zurück. Wie das funktioniert, kann man im Quelltext nachlesen.

Kommandostrings

Wie schon gesagt, basiert MCI auf Kommandostrings, die mit mciSendString(…) versand werden. Zu den wichtigsten Kommandos gehören:
open
play
stop
pause
close

All diesen Kommandos können noch zusätzliche Parameter übergeben werden, die das Verhalten des Befehls genauer spezifizieren.
Beim open Kommando sieht das dann so aus:
open “C:\Videos\test.avi“ type mpegvideo alias VideoStream

Dieser Befehl öffnet die Datei test.avi und macht sie unter dem Alias VideoStream verfügbar. Diese Aliase sind für die weitere Ansteuerung über Kommandos wichtig. So kann man die Wiedergabe mit
play VideoStream fullscreen

beginnen und mit
stop VideoStream

wieder anhalten.
close VideoStream

schließt unseren Stream.

Das schöne an der Sache ist, dass diese Syntax für fast alle Medientypen mehr oder minder identisch ist. Auch MP3s und CDs lassen sich damit abspielen (siehe Quellcode).

Der zusätzliche Parameter fullscreen im Play-Kommando ist optional und entscheidet nur darüber, ob das Video im Vollbildmodus abgespielt wird oder nicht.

Für Audio-CDs kann man auch die CD Klappe öffnen und schließen. Dazu sendet man einfach folgende Kommandos:
set cdaudio door open
und
set cdaudio door closed

Alle Befehlsstrings zu behandeln, würde hier wohl den Rahmen sprengen. Auf MSDN werden sie alle ausführlich beschrieben:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_mci_reference.asp

Beispielprogramm

Ich habe für diesen Artikel einen kleinen Multimedia-Player geschrieben, der die Verwendung der MCI-Bibliothek demonstriert:

// Update (18.06.05): Habe einen Bug im Programm entfernt. Der Player sollte jetzt besser mit aufretenden Fehlern umgehen (z.B. wenn keine CD eingelegt ist)
Attachments
I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.
private Nachricht | Beiträge des Benutzers
dr4g0n76
myCSharp.de - Experte

Avatar #avatar-1768.jpg


Dabei seit:
Beiträge: 2.921
Herkunft: Deutschland

beantworten | zitieren | melden

Ja damit kann man vor allem auch gut CD-Laufwerk auf/zu machen und z.B. den Motor anhalten. ;-)
Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.
private Nachricht | Beiträge des Benutzers
alf468
myCSharp.de - Member



Dabei seit:
Beiträge: 196

beantworten | zitieren | melden

Ich möchte gerne alle mp3s aus einem Ordner abspielen.

public void getlieder()
		{
			String[] files=Directory.GetFiles(Data.musik,"*.mp3");
			foreach(string name in files)
			{
				//System.Windows.Forms.Application.DoEvents();
				if(this._play==true)
				{
					this.name=name;
					string cmd = "open \"" + name + "\" type " + "mpegvideo" + " alias \"" + name + "\"";
					int errCode = mciSendString(cmd, null, 0, IntPtr.Zero);
					CheckError(errCode);
					this.SetTimeFormat("m");
					String time=this.GetLength();
					this.Play(time);
			                                System.Threading.Thread.Sleep(int.Parse(time));
					
				}
				else
				{
						break;
				}
			}
		}

So werden zwar alle Lieder abgespielt aber es dauert immer etwas bis ein neues Lied anfängt.
Habt ihr bessere Vorschläge?

PS.: Der Musikplayer läuft als Thread neben den eigentlichen Programm.
private Nachricht | Beiträge des Benutzers
SGT_BOB
myCSharp.de - Member



Dabei seit:
Beiträge: 125
Herkunft: Aachen

beantworten | zitieren | melden

Hallo Leute.

Ich hab ebenfalls eine Frage.

Ich setze mit


			mciCommand = "set \"" + currentTrack + "\" time format ms";
			mciErrorCode = mciSendString(mciCommand, null, 0, IntPtr.Zero);

das Zeitformat auf Millisekunden
und lese mit


		private string GetLength()
		{
			Console.WriteLine(currentTrack);

			StringBuilder buffer = new StringBuilder(256);
			mciCommand = "status \"" + currentTrack + "\" length";
			mciErrorCode = mciSendString(mciCommand, buffer, 256, IntPtr.Zero);
			return buffer.ToString();
		}

die Länge des Tracks ein.

Leider ist der zurückgegebene String leer ("").
Weiß jemand wieso? Ich hab es genau wie in dem Beispiel im Anhang. Dort funktioniert es auch wunderbar.

Was mach ich falsch?

Mfg SGT_BOB
*************************
Ich bin root, ich darf das...
root>_
*************************
private Nachricht | Beiträge des Benutzers
maxE
myCSharp.de - Member



Dabei seit:
Beiträge: 456
Herkunft: Sachsen

Themenstarter:

beantworten | zitieren | melden

Ich häng in diesem MCI Kram nicht so tief drinn, aber es kann an ein deinem geöffnetem Gerät liegen. Nicht alle Geräte unterstützen alle Zeitformate.
CD-Devices haben üblicherweise das Format Track:Minute:Second:Millisecond.
I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.
private Nachricht | Beiträge des Benutzers
SGT_BOB
myCSharp.de - Member



Dabei seit:
Beiträge: 125
Herkunft: Aachen

beantworten | zitieren | melden

Hi maxE.

Erst mal danke für die Antwort. Aber dein Beispiel funktioniert ja. Ich öffne das selbe MP3-File. Beim Beispiel-Programm funztes, bei meinem bekomme ich einen Fehlercode (263, glaub ich) zurück.

Noch irgendeine Ahnung?

Mfg SGT_BOB



EDIT:

Hat sich gerade erledigt. Ich weiß zwar nicht wieso, aber ich habe es jetzt geschafft. Danke trotzdem.
*************************
Ich bin root, ich darf das...
root>_
*************************
private Nachricht | Beiträge des Benutzers
lex
myCSharp.de - Member



Dabei seit:
Beiträge: 113
Herkunft: Niedersachsen

beantworten | zitieren | melden

moin,

hab dazu noch mal eine frage, kennt sich hier wer zufällig mit der Quartz.dll aus?

hätte da noch ein paar fragen und würde mich übner hilfe sehr freuen!

1.) ich kann 2 stuecke zur gleichen Zeit abspielen, sehr ungünstig!
2.) pause hat ne zeitverzögerung von knapp 10sec, viel zu lange!!!
private Nachricht | Beiträge des Benutzers
Slowflyer
myCSharp.de - Member



Dabei seit:
Beiträge: 1
Herkunft: NRW

Video in das Hauptfenster einbauen

beantworten | zitieren | melden

Hallo,

mit Interesse habe ich diesen Artikel gelesen und danch gleich ausprobiert. Ich kann auch Videos abspielen. nun stoße ich jedoch auf ein Problem: die Videos werden in einem separaten Fenster geöffnet. Ich hätte aber gerne, dass das Video in meinem Hauptfenster (vielleicht in irgensdeinem Control) in einer definierten Größe abgespielt wird. Wie stellt man soetwas an?

Gruß, Slowflyer
private Nachricht | Beiträge des Benutzers
SkySurfer
myCSharp.de - Member



Dabei seit:
Beiträge: 298
Herkunft: bei Stuttgart

beantworten | zitieren | melden

Hi,

du kannst dem MCI ein Handle von z.B. einer Picturebox übergeben in der die Wiedergabe dann ablaufen soll.

[DllImport("winmm.dll")]
private static extern int mciSendString(string cmd, StringBuilder ret, int retLen, IntPtr hwnd);

einfach dem IntPtr hwnd z.B. ein PictureBox.handle übergeben anstatt eines IntPtr.Zero

Gruß SkySurfer
Es gibt 11 Arten von Menschen:
- Die, die binär verstehen
- Die, die es nicht tun
- Die, die Witze darüber machen
private Nachricht | Beiträge des Benutzers
wmieh
myCSharp.de - Member



Dabei seit:
Beiträge: 3

beantworten | zitieren | melden

Sehr guter Beitrag, hat mich wirklich weiter gebracht.

Ich habe allerdings noch nicht herausgefunden, wie ich abfragen kann wann ein Titel zuende gespielt wurde. Vielleicht kann mir da jemand helfen...danke im voraus.
private Nachricht | Beiträge des Benutzers
Seikilos
myCSharp.de - Member



Dabei seit:
Beiträge: 753

beantworten | zitieren | melden

Hallo,
mir geht es genauso, ich suche ein Event oder ähnliches, was mir sagt, ob das Lied gerade zu ende gespielt worden ist, oder nicht.
Im Moment sehe ich da nur die Möglichkeit zu vergleichen ob getcurrentPos == getLength ist
Life is a short
private Nachricht | Beiträge des Benutzers
zeax
myCSharp.de - Member



Dabei seit:
Beiträge: 38

beantworten | zitieren | melden

ich wollte fragen wie ich statt einer datei einfach den teil der zur zeit gerade über meine soundkarte ausgegeben wird. abgreifen kann um ihn dann so über das netzwerk zu verschicken und an einem anderen rechner mithilfe von mci abspielen kann

gruß zeax
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Als Ergänzung dieses Tutorials...

Hier noch ein Link wie man auch die Events von MCI nutzen kann.

Mp3 Stream abspielen
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Durin-V
myCSharp.de - Member



Dabei seit:
Beiträge: 43

beantworten | zitieren | melden

Hi Leute,

zu dem Pointer mit der PictureBox.
Ich hab die Funktionen der MCI aus deinem Beispiel Code direkt übernommen. Das einzige was ich daran geändert habe ist das dich dem ganzen noch einen Konstruktor spendiert habe bei dem ich dann den IntPtr einer Picture Box übergebe der dann in der Klasse als private Variable gespeichert wird.
Außerdem habe ich alle IntPtr.Zero durch den Variablennamen ersetzt. Doch wenn ich nun mit meiner Funktion eine Video ansehen will, öffnet er mir dieses immer noch in einem separatem Fenster.

Woran kann das liegen?

Gruß
Durin-V
Die drei Erzfeinde eines jeden Programmierers:
1. Tageslicht
2. Frischluft
3. das Gebrüll der Vögel
private Nachricht | Beiträge des Benutzers
TheBrainiac
myCSharp.de - Member

Avatar #avatar-3152.png


Dabei seit:
Beiträge: 795
Herkunft: /dev/null

beantworten | zitieren | melden

Du musst das Handle der PictureBox (oder Form oder sonstwas) im CommandString mit übergeben :

mciSendString("open \"" + name + "\" type mpegvideo alias \"" + name + "\" parent " + pictureBox1.Handle.ToInt32().ToString() + " style child", null, 0, IntPtr.Zero);

Nun zu meiner Frage: Wie findet man die Originalgröße des Videos heraus?

Gruß, Christian.
There are 10 types of people in the world:
Those, who think they understand the binary system
Those who don't even have heard about it
And those who understand "Every base is base 10"
private Nachricht | Beiträge des Benutzers
confused
myCSharp.de - Member



Dabei seit:
Beiträge: 62

beantworten | zitieren | melden

Hallo!

Ich habe ein Problem mit der Wiedergabe...wenn ich das Beispielprogramm verwende funktionniert es ohne Probleme, kopiere ich allerdings die SimpleAudioVideoPlayback.cs in ein anderes Projekt und erstelle dort eine neue Instanz und rufe Open() auf, bekomme ich einen Fehler:

Unbekanntes Problem beim Laden des angegebenen Gerätetreibers.


static void Main(string[] args)
{
   MCIPlayback m = new MCIPlayback();            
   m.Open(@"C:\c.mp3", "mpegvideo");
}

Weiß jemand, woran das liegen könnte? Hat es vielleicht damit zu tun, dass es einmal eine Windowsapplikation ist, und das andere mal liegt die Datei in einer DLL und wird von obiger Main aufgerufen?
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von confused am .
private Nachricht | Beiträge des Benutzers
confused
myCSharp.de - Member



Dabei seit:
Beiträge: 62

beantworten | zitieren | melden

Ok, ich habe den Fehler gefunden:

Aus irgendeinem Grund muss das Programm, das ausgeführt wird und diese MCI-Sachen aufruft mit [STAThread] gekennzeichnet sein.

Kriegt man dieses Problem noch in den Griff?! Ansonsten bin ich soweit fertig!
private Nachricht | Beiträge des Benutzers
ForceDragonX
myCSharp.de - Member



Dabei seit:
Beiträge: 17

beantworten | zitieren | melden

Zitat
Original von Schamese
Nun zu meiner Frage: Wie findet man die Originalgröße des Videos heraus?

Gruß, Christian.

Würde mich auch interessieren.

Aber was ich auch wissen will: Kann man das Video 'verkleinern', sodass, wenn man das Form mit der Picturebox (die das Video anzeigt) verkleinert, das Video nicht einfach abgeschnitten wird, sondern sich mit verkleinert.
private Nachricht | Beiträge des Benutzers
cemizm
myCSharp.de - Member



Dabei seit:
Beiträge: 11
Herkunft: Bielefeld

beantworten | zitieren | melden

Dock doch einfach mal die Picturebox in der Form so das die Picutrebox immer die ganze Form füllt.

Mfg
private Nachricht | Beiträge des Benutzers
Hunv
myCSharp.de - Member

Avatar #avatar-3429.png


Dabei seit:
Beiträge: 193

beantworten | zitieren | melden

Zitat
Original von confused
Ok, ich habe den Fehler gefunden:

Aus irgendeinem Grund muss das Programm, das ausgeführt wird und diese MCI-Sachen aufruft mit [STAThread] gekennzeichnet sein.

Kriegt man dieses Problem noch in den Griff?! Ansonsten bin ich soweit fertig!

Danke! Hat mir echt weitergehofen!

Edit:
Achja: und kann man die Lautstärke verändern oder muss das über den Wave-Kanal erledigt werden?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Hunv am .
Visit me @ www.beremote.net
private Nachricht | Beiträge des Benutzers
Hunv
myCSharp.de - Member

Avatar #avatar-3429.png


Dabei seit:
Beiträge: 193

beantworten | zitieren | melden

Aaalso:
Man kann die Lautstärke verändern.
Die MCI-SendStrings sind wie folgt:
Linker Audiokanal:
mciSendString(string.Concat("setaudio MediaFile left volume to ", value), null, 0, 0);

Rechter Audiokanal:
mciSendString(string.Concat("setaudio MediaFile right volume to ", value), null, 0, 0);

Master Kanal:
mciSendString(string.Concat("setaudio MediaFile volume to ", value), null, 0, 0);

value hat dabei einen Wert von 0 bis 1000


Zusätzlich kann man angeblich noch Bass und Treble verändern, aber bei mir funktioniert es nicht. Trotzdem hier die Strings dafür (auch hier hat Value einen Wert von 0 bis 1000):
mciSendString(string.Concat("setaudio MediaFile bass to ", value), null, 0, 0);
mciSendString(string.Concat("setaudio MediaFile treble to ", value), null, 0, 0);
Visit me @ www.beremote.net
private Nachricht | Beiträge des Benutzers
Wanginator
myCSharp.de - Member



Dabei seit:
Beiträge: 33
Herkunft: Berlin

beantworten | zitieren | melden

Ist die winmm.dll standardmäßig bei allen Windows-Versionen (ab 98) nach der Neuinstallation mit dabei? Muss wissen ob mciSendString universell einsetzbar ist für versch. OS-Versionen
private Nachricht | Beiträge des Benutzers
TheBrainiac
myCSharp.de - Member

Avatar #avatar-3152.png


Dabei seit:
Beiträge: 795
Herkunft: /dev/null

beantworten | zitieren | melden

MCI gibt es imho seit Win3.1x. Man muss nur die Audiocodecs nachinstallieren, die man braucht.

Gruß, Christian.
There are 10 types of people in the world:
Those, who think they understand the binary system
Those who don't even have heard about it
And those who understand "Every base is base 10"
private Nachricht | Beiträge des Benutzers
TimeOver
myCSharp.de - Member



Dabei seit:
Beiträge: 1
Herkunft: Bayern

beantworten | zitieren | melden

Hallo,
dieser Thread ist zwar schon etwas älter, ich habe aber trotzdem noch eine Frage dazu. Und zwar möchte ich bestimmte Frames des Videos als Bitmap, Color-Array oder vergleichbares bekommen, diese bearbeiten und wieder in ein video(avi) speichern. Auch den Sound möchte ich entfernen und wieder hinzufügen können. Ist dies mit MCI möglich oder kennt ihr noch andere Möglichkeiten?
Ich hoffe sehr, dass mir jemand weiterhelfen kann, ich google nämlich schon seit längerem und das einzige vernünftige, was ich bekommen habe ist das hier:
http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx
Leider gab es hier aber zu oft AVIs, die nicht geöffnet werden konnten.

mfg

TimeOver
Hi Leute
bin 14 Jahre alt, intressiere mich seit ich 10 bin für die Programmierung und programmiere seit ich 13 bin selber

Meine Kentnisse:
html, css, php, mysql, C#, XNA und ein wenig C++
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10.007

beantworten | zitieren | melden

Nein, MCI ist nicht für Videobearbeitung gedacht.

Wenn Du dir mal Projekte wie VirtualDup und CO anschaust, wirst Du feststellen,
das das alles nicht wirklich einfach ist.
private Nachricht | Beiträge des Benutzers