#c# #audio #directshow
#c# #Аудио #directshow
Вопрос:
Я пишу программу, которая захватывает аудио на C #, используя библиотеку DirectShow, и записывает его в контейнер ogg. Я создал график в GraphEditPlus. Он генерирует код метода GraphBuilder, который я скопировал в свой код. Этот код является:
class AudioCapture
{
public static void checkHR(int hr, string msg)
{
if (hr < 0)
{
MessageBox.Show(msg);
DsError.ThrowExceptionForHR(hr);
}
}
public static void BuildGraph (IGraphBuilder pGraph, string dstFile)
{
int hr = 0;
//graph builder
ICaptureGraphBuilder2 pBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = pBuilder.SetFiltergraph(pGraph);
checkHR(hr, "Can't SetFiltergraph");
Guid CLSID_XiphOrgVorbisEncoder = new Guid("{5C94FE86-B93B-467F-BFC3-BD6C91416F9B}");
Guid CLSID_XiphOrgOggMuxer = new Guid("{1F3EFFE4-0E70-47C7-9C48-05EB99E20011}");
//add microphone
IBaseFilter pMicrophone = (IBaseFilter) new AudioRecord();
hr = pGraph.AddFilter(pMicrophone, "Microphone");
checkHR(hr, "Can't add microphone to graph");
//add Vorbis Encoder
IBaseFilter pVorbisEncoder = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_XiphOrgVorbisEncoder));
checkHR(hr, "Can't add Vorbis Encoder to graph");
//connect Microphone and Vorbis Encoder
hr = pGraph.ConnectDirect(GetPin(pMicrophone, "Capture"), GetPin(pVorbisEncoder, "PCM In"), null);
checkHR(hr, "Can't connect Microphone and Vorbis Encoder");
//add Ogg Muxer
IBaseFilter pOggMuxer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_XiphOrgOggMuxer));
checkHR(hr, "Can't add Ogg Muxer to graph");
//set destination filename
IFileSinkFilter pOggMuxer_sink = pOggMuxer as IFileSinkFilter;
if (pOggMuxer_sink == null)
checkHR(unchecked((int)0x80004002), "Can't get IFileSinkFilter");
hr = pOggMuxer_sink.SetFileName(dstFile, null);
checkHR(hr, "Can't set filename");
//connect Vorbis Encoder and Ogg Muxer
hr = pGraph.ConnectDirect(GetPin(pVorbisEncoder, "VorbisOut"), GetPin(pOggMuxer, "Ogg Packet In"), null);
checkHR(hr, "Can't connect Vorbis Encoder and Ogg Muxer");
}
static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
checkHR(-1, "Pin not found");
return null;
}
}
Когда я пытаюсь выполнить этот код, программа выдает мне сообщение «Pin-код не найден» после попытки подключить фильтры микрофона и кодировщика vorbis. После отладки я обнаружил, что он не может найти вывод микрофона. Кто-нибудь знает, где моя ошибка?
Комментарии:
1. Лучше искать устройство ввода звука. just
new AudioRecord()
не создает автоматически вход micropone.2. Привет, как записать видео и аудио и сохранить его в один видеофайл? Я могу сделать это с помощью отдельных файлов. не могли бы вы мне помочь.
Ответ №1:
Вам не следует искать пин-коды по их названиям, так как это не совсем надежно. Возможно, это может быть еще более или менее приемлемо, если вы абсолютно уверены, с каким фильтром / классом вы имеете дело, но это определенно не тот способ, которым можно использовать общий фильтр источника звука (более конкретно: никто не обещает, что pin-код захвата называется «Capture», вместо этого pin-коды реализуются IKsPropertySet
, чтобы указать это).
Вашим лучшим подходом было бы использовать аргумент ICaptureGraphBuilder::RenderStream
with PIN_CATEGORY_CAPTURE
, чтобы он мог подобрать для вас pin-код захвата. Смотрите MSDN для получения подробной информацииhttp://msdn.microsoft.com/en-us/library/dd311932(v=vs.85).aspx и я почти уверен, что вы легко найдете пример кода и для этого.
Ответ №2:
Попробуйте сделать что-то подобное, когда вы ищете пины
pinout = FindPinByDirection( Source, PinDirection.Output);
pinin = FindPinByDirection( Target, PinDirection.Input);
Graph.Connect(pinout, pinin);
Это лучший способ, чем в зависимости от имен.