0
votes

I would like to record the microphone and the system sound
(Youtube music, Media Player movie sound, keyboard type warning sound...etc.),
so that publishing it to the server by Flash Player.

I found the DirectShow sample at GitHub: virtual-audio-capture-grabber-device
I register its DLL successfully.
And the filter name of this sample is "virtual-audio-capturer".

C:\Users\user\Desktop\virtual-audio-capture-grabber-device-master\virtual-aud
io-capture-grabber-device-master\source_code\Release>regsvr32 audio_sniffer.dll

I used virtual-audio-capturer filter of Audio Capture Source,
WavDest Filter and File Writer Filter to record audio into the WAVE file by GraphEdt.exe.
The graph is workable. And the result file is correct.

There are Microphone (VIA High Definition Audio) and Stereo Mix (VIA High Definition Audio) in the microphone list of Flash Player, but no virtual-audio-capture-grabber-device. The result is same with Action Script 3 project. But I can see the virtual-audio-capture-grabber-device at Adobe Flash Media Live Encoder 3.2. (http://img.bbs.csdn.net/upload/201311/12/1384239370_718116.png)

var deviceArray:Array = Microphone.names;

trace("Available sound input devices:"); 
for (var i:int = 0; i < deviceArray.length; i++) { 
    trace(" " + deviceArray[i]); 
} 


The virtual-audio-capturer filter has only one output pin, and no input pin.

    const AMOVIESETUP_MEDIATYPE AMSMediaTypesVCam = 
    {     &MEDIATYPE_Audio,      // clsMajorType
          &MEDIASUBTYPE_NULL     // clsMinorType
    }; 


setup.cpp

#define CreateComObject(clsid, iid, var) CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, iid, (void **)&var);

STDAPI AMovieSetupRegisterServer( CLSID   clsServer, LPCWSTR szDescription, LPCWSTR szFileName, LPCWSTR szThreadingModel = L"Both", LPCWSTR szServerType     = L"InprocServer32" );
STDAPI AMovieSetupUnregisterServer( CLSID clsServer );

#ifdef _WIN64
DEFINE_GUID(CLSID_VirtualCam,
        0x8e146464, 0xdb61, 0x4309, 0xaf, 0xa1, 0x35, 0x78, 0xe9, 0x27, 0xe9, 0x35);
#else
DEFINE_GUID(CLSID_VirtualCam,
        0x8e14549b, 0xdb61, 0x4309, 0xaf, 0xa1, 0x35, 0x78, 0xe9, 0x27, 0xe9, 0x35);
#endif

const AMOVIESETUP_MEDIATYPE AMSMediaTypesVCam = { &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL }; 

const AMOVIESETUP_PIN AMSPinVCam = {
L"Output",             // Pin string name
FALSE,                 // Is it rendered
TRUE,                  // Is it an output
FALSE,                 // Can we have none
FALSE,                 // Can we have many
&CLSID_NULL,           // Connects to filter
NULL,                  // Connects to pin
1,                     // Number of types
&AMSMediaTypesVCam };

const AMOVIESETUP_FILTER AMSFilterVCam = {
&CLSID_VirtualCam,  // Filter CLSID
L"virtual-audio-capturer",     // String name
MERIT_DO_NOT_USE,      // Filter merit
1,                     // Number pins
&AMSPinVCam };

CFactoryTemplate g_Templates[] = {
{
    L"virtual-audio-capturer",
    &CLSID_VirtualCam,
    CVCam::CreateInstance,
    NULL,
    &AMSFilterVCam
}, };

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

STDAPI RegisterFilters( BOOL bRegister ) {
HRESULT hr = NOERROR;
WCHAR achFileName[MAX_PATH];
char achTemp[MAX_PATH];
ASSERT(g_hInst != 0);

if( 0 == GetModuleFileNameA(g_hInst, achTemp, sizeof(achTemp))) 
    return AmHresultFromWin32(GetLastError());

MultiByteToWideChar(CP_ACP, 0L, achTemp, lstrlenA(achTemp) + 1, 
                   achFileName, NUMELMS(achFileName));

hr = CoInitialize(0);
if(bRegister) {
    hr = AMovieSetupRegisterServer(CLSID_VirtualCam, L"virtual-audio-capturer", achFileName, L"Both", L"InprocServer32");
}

if( SUCCEEDED(hr) ) {
    IFilterMapper2 *fm = 0;
    hr = CreateComObject( CLSID_FilterMapper2, IID_IFilterMapper2, fm );
    if( SUCCEEDED(hr) )
    {
        if(bRegister)
        {
            IMoniker *pMoniker = 0;
            REGFILTER2 rf2;
            rf2.dwVersion = 1;
            rf2.dwMerit = MERIT_DO_NOT_USE;
            rf2.cPins = 1;
            rf2.rgPins = &AMSPinVCam;
            hr = fm->RegisterFilter(CLSID_VirtualCam, L"virtual-audio-capturer", &pMoniker, &CLSID_AudioInputDeviceCategory, NULL, &rf2);
        }
        else
        {
            hr = fm->UnregisterFilter(&CLSID_AudioInputDeviceCategory, 0, CLSID_VirtualCam);
        }
    }

  // release interface
  if(fm)
      fm->Release();
}

if( SUCCEEDED(hr) && !bRegister )
    hr = AMovieSetupUnregisterServer( CLSID_VirtualCam );

CoFreeUnusedLibraries();
CoUninitialize();
return hr; }

#include <stdio.h>

STDAPI RegisterFilters( BOOL bRegister );

STDAPI DllRegisterServer() {
printf("hello there"); // we actually never see this...
return RegisterFilters(TRUE); }

STDAPI DllUnregisterServer() {
return RegisterFilters(FALSE); }

STDAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved) {
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); 

Please click the link to view the full DirectShow sample code.

Is the DirectShow virtual audio device available with Flash Player?
Should I add the Analog Audio input pin?
Should I implement the IAMAudioInputMixer interface?
Should I use WinDDK to make the virtual audio device first?

Win7 SP1 64Bit System;
VIA High Definition Audio;
Intel Audio;
Adobe Flash Media Live Encoder 3.2
Adobe Flash Player 11,8,800,94
Adobe Flash Builder 4.6
Microsoft Visual C++ 2010
Microsoft Windows SDK 7.1

1

1 Answers

0
votes

I cannot know for sure, but Flash probably does not use DirectShow API for audio, but instead another of Windows' many audio APIs, probably DirectSound. You'll have to write an audio driver.