DirectX.Capture - rejestrowanie dźwięku i obrazu w C#
Dodany: 15:30, wtorek, 20 kwietnia 2010
Na temat rejestrowania dźwieku i obrazu w technologi .NET w internecie można znaleźć wiele informacji. Moją uwagę przykuł jednak artykuł sprzed kilku lat (kliknij źródło) opisujący biblioteke DirectX.Capture, która jest rozwinięciem biblioteki DShowNet, oraz prezentujący gotową aplikacje do rejestrowania dźwięku i obrazu. W tym artykule postaram się opisać w prosty sposób, jak korzystając z języka C#, biblioteki DirectX.Capture, programu Visual Studio 2008 oraz Windows Forms można w łatwy i szybki sposób stworzyć aplikacje do nagrywania obrazu i dźwięku.
Pierwszym krokiem jaki należy zrobić, jest stworzenie nowego projektu - Windows Forms Application, podanie jego nazwy, oraz zapisanie w odpowiednim katalogu (u mnie będzie się on nazywał DirectXCaptureTest). Po zatwierdzeniu ukaże się nam okno czystej aplikacji systemu Windows. W zakładce Properties możemy zmienić nazwe naszego okna (w moim przypadku DirectX.CaptureTest). Kolejnym krokiem jest dodanie referencji do gotowej biblioteki DirectX.Capture.dll (prawym na nazwe projektu->Add Reference->zakładka Browse->a następnie dodajemy nasza biblioteke DirectX.Capture.dll). Ważnym elementem jest także to, aby zadeklarować używanie danej biblioteki na początku pliku Form1.cs. Poniższy kod ilustruje jak ma to wyglądać.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DirectX.Capture;
Kolejnym krokiem jest stworzenie interfejsu użytkownika, czyli dodanie odpowiedniego Panelu do wyświetlania obrazu z kamery, przycisków do ustawiania odpowiedniego urządzenia rejestrującego, kolejnych do obsługi zdarzeń oraz pola dialogowego, które będzie odpowiedzialne za zapis naszego pliku. Pierwszym co należy w tym momencie zrobić, jest zwiększenie wielkości naszej aplikacji, aby wszystkie te elementy mogły się pomieścić. Kolejnym krokiem jest dodanie z paska ToolBox kontrolki o nazwie Panel do okna aplikacji, zmiany nazwy danego elementu (pole Name) na pPreview i rozszerzenie jej do odpowiednio dużych rozmiarów (obraz z kamery w zależności od rozdzielczości może być duży, lub mały). Następnie dodajemy 2 kontrolku typu ComboBox (o nazwach cbVideo i cbAudio), w celu ładowania aktywnych urządzeń do rejestrowania dźwięku i obrazu, oraz przycisk (Button) obsługujący zdarzenie, którego zadaniem będzie wyświetlanie obrazu w załączonym panelu (o nazwie bPreview). Powinny pojawić się także 2 przyciski obsługujące zdarzenie startu i stopu zapisu (odpowiednio bStart i bStop, oraz ustawiamy w Properties przy przycisku Stop opcje Enabled na false). Użytkownik powinien mieć możliwość zapisu rejestrowanego pliku w dowolnym folderze, oraz pod dowolna nazwą - do tego służy kontrolka saveFileDialog, z zakładki Dialog. Dodanie jej do projektu umożliwi użytkownikowi w łatwy sposób obsługe zapisu pliku. Należy także zmienić jej nazwe (u mnie sfdFile), oraz dodać kolejny przycisk do obsługi zdarzeń (bFile) i opcjonalnie pole tekstowe (TextBox) do wyświetlania aktualnej ścieżki do pliku (w Properties zmienić opcje ReadOnly na true i nazwe na tbFile). Poniżej znajduje się zrzut ekranu jak powinno to wyglądać.

Kod obsługujący naszą aplikacje nie jest skomplikowany. Na początku powinna znaleźć się deklaracja dwóch zmiennych globalnych - jednej do obsługi nagrywania, a drugiej do obsługi wszystkich filtrów.
public partial class Form1 : Form
{
private Capture capture = null;
private Filters filters = new Filters();
Następnie w zdarzeniu odpowiedzialnym za ładowanie okna powinien znaleźć się kod wczytujący i wypisujący wszystkie dostępne urządzenia audio i video do ComboBox'ów, gdzie użytkownik będzie miał możliwość wyboru danego urządzenia.
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < filters.VideoInputDevices.Count; i++) cbVideo.Items.Add(filters.VideoInputDevices[i].Name);
for (int i = 0; i < filters.AudioInputDevices.Count; i++) cbAudio.Items.Add(filters.AudioInputDevices[i].Name);
}
Ustawianie urządzeń audio i video powinno odbywać się po każdorazowym wyborze elementu z rozwijanej listy. Zdarzenia te można wygenerować dwa razy naciskając na kontrolki cbAudio i cbVideo.
private void cbVideo_SelectedIndexChanged(object sender, EventArgs e)
{
Filter videoDevice = null;
Filter audioDevice = null;
if (capture != null)
{
videoDevice = capture.VideoDevice;
audioDevice = capture.AudioDevice;
capture.Dispose();
capture = null;
}
int m = cbVideo.SelectedIndex;
videoDevice = (m > -1 ? filters.VideoInputDevices[m] : null);
if ((videoDevice != null) || (audioDevice != null))
{
capture = new Capture(videoDevice, audioDevice);
}
private void cbAudio_SelectedIndexChanged(object sender, EventArgs e)
{
Filter videoDevice = null;
Filter audioDevice = null;
if (capture != null)
{
videoDevice = capture.VideoDevice;
audioDevice = capture.AudioDevice;
capture.Dispose();
capture = null;
}
int m = cbAudio.SelectedIndex;
audioDevice = (m > -1 ? filters.AudioInputDevices[m] : null);
if ((videoDevice != null) || (audioDevice != null))
{
capture = new Capture(videoDevice, audioDevice);
}
}
Zadaniem powyższego kodu jest zapisywanie dotychczasowo ustawionych urządzeń i nadpisywanie jedynie tych, które są zmieniane. Ponieważ ustawione urządzenie nie może być zmieniane podczas trwania programu, dlatego zasoby są zwalniane, zmienna jest ustawiana na null, a następnie za pomocą konstruktora tworzony jest nowy obiekt z nowymi wartościami.
Kolejnym krokiem jest obsługa przycisku podglądu obrazu. Naciskając dwa razy na przycisk w oknie projektowania wyglądu aplikacji utworzy nam się zdarzenie odpowiedzialne za naciśnięcie na przycisk.
private void bPreview_Click(object sender, EventArgs e)
{
try
{
if (capture == null)
{
throw new ApplicationException("Prosze wybrac urządzenie video i/lub audio.");
}
capture.PreviewWindow = pPreview;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.ToString());
}
}
Obsługa podglądu rozpoczyna się od sprawdzenia, czy jest ustawione urządzenie odtwarzające obraz. Jeżeli go nie ma, program zgłosi wyjątek, w przeciwnym wypadku obraz z kamery powinien pojawić się we wcześniej zdefiniowanej kontrolce.
Kolejnym krokiem jest obsługa zdarzenia odpowiedzialnego za podanie odpowiedniej ścieżki do pliku i jego nazwy. Za ten element odpowiada zmienna sfdFile.
private void bFile_Click(object sender, EventArgs e)
{
sfdFile.FileName = "testfile";
sfdFile.Filter = ".avi|";
sfdFile.DefaultExt = ".avi";
sfdFile.ShowDialog();
tbFile.Text = sfdFile.FileName;
}
Na początku powyższego kodu ustawiamy nazwe domyślnego pliku na testfile, oraz jego rozszerzenie na *.avi. Następnie użytkownikowi ukaże się okno dialogowe z możliwością wybrania folderu i nazwy zapisywanego pliku. Po zatwierdzeniu, ścieżka do pliku ukaże się w polu tekstowym tbFile.
Kolejnym, a zarazem ostatnim krokiem jest dodanie obsługi zdarzeń dla przycisku Startu oraz Stopu.
private void bStart_Click(object sender, EventArgs e)
{
try
{
if (capture == null)
{
throw new ApplicationException("Prosze wybrac urządzenie video i/lub audio.");
}
if (!capture.Cued)
{
if (tbFile.Text == "")
{
throw new ApplicationException("Prosze wybrać folder zapisu pliku.");
}
capture.Filename = tbFile.Text;
}
capture.Start();
bStart.Enabled = false;
bStop.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.ToString());
}
}
private void bStop_Click(object sender, EventArgs e)
{
try
{
if (capture != null)
{
capture.Stop();
bStart.Enabled = true;
bStop.Enabled = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.ToString());
}
}
Kod obsługujący przycisk Start jest odpowiedzialny za sprawdzenie, czy jest ustawione urządzenie audio i/lub video, oraz jest wybrany katalog, gdzie będzie zapisywany dany plik. Następnie pobierana jest ścieżka do pliku, w którym będzie on zapisywany, uruchamiana jest rejestracja obrazu, oraz odblokowywany jest przycisk Stop, a blokowany przycisk Start. Obsługa przycisku Stop polega tylko i wyłącznie na zatrzymaniu nagrywania, oraz odblokowaniu przycisku Start i zablokowaniu przycisku Stop.
Poniżej znajduję sie zrzut ekranu programu rejestrującego obraz z kamery internetowej za pomocą biblioteki DirectX.Capture. W razie jakichkolwiek pytań, zapraszam do działu Kontakt.




