需求是能够在 asp.net 的客户端页面上提供录制音频的功能,音频录制后要保持到服务器上,任何格式都可以。
这个网站类似于托福考试: http://i-courses.org/?p=sample_tests
在考试的时候播放题目,要求学生在规定的时间内在网站的页面上用在线录音。

解决方案 »

  1.   

    用FLASH能行,这类东西多半用FLASH来做
      

  2.   

    ActiveX在线录音
    flash调用录音设备 FMS
      

  3.   

    本人不会 Flash, 现学是不是很麻烦啊。
    现在微软新出的技术 SilverLight 4, 好像支持录音录像,但是网上这样的例子很少,我找到的那个例子录音钢琴的那个好像也不是真的录音,而是把钢琴键记住后再播放。
    希望有 SilverLight 的高手,指点一下,如何用 SilverLight 实现在线录制音频功能。
      

  4.   


    我想过这个方法,是调用客户端本机上的 MediaPlayer 来实现录音功能的吗?
      

  5.   

    现学FLASH比现学SILVERLIGHT容易很多
      

  6.   

    貌似好象flash更好学一点的样子
      

  7.   

    还有没有其他的意见?除了flash?
      

  8.   

    三.代码解析(SoundRecord类) 1.需要引用的程序集using System; 
    using System.Windows.Forms; 
    using System.Threading; 
    using System.IO;
    using Microsoft.DirectX; 
    using Microsoft.DirectX.DirectSound;
    2. SoundRecord的成员数据public const int cNotifyNum = 16; // 缓冲队列的数目
    private int mNextCaptureOffset = 0; // 该次录音缓冲区的起始点
    private int mSampleCount = 0; // 录制的样本数目
    private int mNotifySize = 0; // 每次通知大小 
    private int mBufferSize = 0; // 缓冲队列大小
    private string mFileName = string.Empty; // 文件名 
    private FileStream mWaveFile = null; // 文件流 
    private BinaryWriter mWriter = null; // 写文件
    private Capture mCapDev = null; // 音频捕捉设备 
    private CaptureBuffer mRecBuffer = null; // 缓冲区对象 
    private Notify mNotify = null; // 消息通知对象
    private WaveFormat mWavFormat; // 录音的格式 
    private Thread mNotifyThread = null; // 处理缓冲区消息的线程 
    private AutoResetEvent mNotificationEvent = null; // 通知事件 3. 对外操作的函数public SoundRecord() 

      // 初始化音频捕捉设备 
      InitCaptureDevice();
      // 设定录音格式 
      mWavFormat = CreateWaveFormat(); 
    }
    public void SetFileName(string filename) 

      mFileName = filename; 
    }
    public void RecStart() { 
      // 创建录音文件 
      CreateSoundFile();
      // 创建一个录音缓冲区,并开始录音 
      CreateCaptureBuffer();
      // 建立通知消息,当缓冲区满的时候处理方法 
      InitNotifications();
      mRecBuffer.Start(true);
    }
    public void RecStop() 

      // 关闭通知消息 
      if (null != mNotificationEvent) 
      mNotificationEvent.Set();
      // 停止录音 
      mRecBuffer.Stop();
      // 写入缓冲区最后的数据 
      RecordCapturedData(); 
      // 回写长度信息 
      mWriter.Seek(4, SeekOrigin.Begin); 
      mWriter.Write((int)(mSampleCount + 36)); // 写文件长度 
      mWriter.Seek(40, SeekOrigin.Begin);
      mWriter.Write(mSampleCount); // 写数据长度 
      mWriter.Close();
      mWaveFile.Close(); 
      mWriter = null; 
      mWaveFile = null; 
    }
      

  9.   

    4.内部调用函数/// <summary> /// 初始化录音设备,此处使用主录音设备. /// </summary> /// <returns>调用成功返回true,否则返回false</returns>private bool InitCaptureDevice() {   // 获取默认音频捕捉设备   CaptureDevicesCollection devices = new CaptureDevicesCollection(); // 枚举音频捕捉设备   Guid deviceGuid = Guid.Empty; // 音频捕捉设备的ID
      if (devices.Count>0)   deviceGuid = devices[0].DriverGuid;   else   {  MessageBox.Show("系统中没有音频捕捉设备");  return false;   }
      // 用指定的捕捉设备创建Capture对象   try   {  mCapDev = new Capture(deviceGuid);   }   catch (DirectXException e)   {  MessageBox.Show(e.ToString());   return false;   }  return true; }
    /// <summary> /// 创建录音格式,此处使用16bit,16KHz,Mono的录音格式/// </summary> /// <returns>WaveFormat结构体</returns> private WaveFormat CreateWaveFormat() {   WaveFormat format = new WaveFormat();
      format.FormatTag = WaveFormatTag.Pcm; // PCM   format.SamplesPerSecond = 16000; // 16KHz   format.BitsPerSample = 16; // 16Bit   format.Channels = 1; // Mono  format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));   format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;  return format; }
    /// <summary> /// 创建录音使用的缓冲区 /// </summary> private void CreateCaptureBuffer() {  // 缓冲区的描述对象   CaptureBufferDescription bufferdescription = new CaptureBufferDescription(); 
      if (null != mNotify)   {  mNotify.Dispose();   mNotify = null;  }   if (null != mRecBuffer)  {   mRecBuffer.Dispose();   mRecBuffer = null;   }
      // 设定通知的大小,默认为1s钟   mNotifySize = (1024 > mWavFormat.AverageBytesPerSecond / 8) ? 1024 : (mWavFormat.AverageBytesPerSecond / 8);   mNotifySize -= mNotifySize % mWavFormat.BlockAlign; 
      // 设定缓冲区大小   mBufferSize = mNotifySize * cNotifyNum;
      // 创建缓冲区描述    bufferdescription.BufferBytes = mBufferSize;   bufferdescription.Format = mWavFormat; // 录音格式
      // 创建缓冲区   mRecBuffer = new CaptureBuffer(bufferdescription, mCapDev);  mNextCaptureOffset = 0; }
    /// <summary>/// 初始化通知事件,将原缓冲区分成16个缓冲队列,在每个缓冲队列的结束点设定通知点./// </summary> /// <returns>是否成功</returns> private bool InitNotifications() {   if (null == mRecBuffer)   {   MessageBox.Show("未创建录音缓冲区");   return false;   }
      // 创建一个通知事件,当缓冲队列满了就激发该事件.   mNotificationEvent = new AutoResetEvent(false);
      // 创建一个线程管理缓冲区事件   if (null == mNotifyThread)   {   mNotifyThread = new Thread(new ThreadStart(WaitThread));   mNotifyThread.Start();   }
      // 设定通知的位置   BufferPositionNotify[] PositionNotify = new BufferPositionNotify[cNotifyNum + 1];   for (int i = 0; i < cNotifyNum; i++)   {   PositionNotify[i].Offset = (mNotifySize * i) + mNotifySize - 1;   PositionNotify[i].EventNotifyHandle = mNotificationEvent.Handle;   }
      mNotify = new Notify(mRecBuffer);    mNotify.SetNotificationPositions(PositionNotify, cNotifyNum);  return true; }
    /// <summary> /// 将录制的数据写入wav文件 /// </summary> private void RecordCapturedData(){   byte[] CaptureData = null;   int ReadPos;   int CapturePos;   int LockSize;
      mRecBuffer.GetCurrentPosition(out CapturePos, out ReadPos);  LockSize = ReadPos - mNextCaptureOffset;   if (LockSize < 0)   LockSize += mBufferSize;
      // 对齐缓冲区边界,实际上由于开始设定完整,这个操作是多余的.   LockSize -= (LockSize % mNotifySize);
      if (0 == LockSize)  return;   // 读取缓冲区内的数据   CaptureData = (byte[])mRecBuffer.Read(mNextCaptureOffset, typeof(byte), LockFlag.None, LockSize);
      // 写入Wav文件  mWriter.Write(CaptureData, 0, CaptureData.Length);
      // 更新已经录制的数据长度.   mSampleCount += CaptureData.Length;
      // 移动录制数据的起始点,通知消息只负责指示产生消息的位置,并不记录上次录制的位置   mNextCaptureOffset += CaptureData.Length;    mNextCaptureOffset %= mBufferSize; // Circular buffer}/// <summary> /// 接收缓冲区满消息的处理线程 /// </summary> private void WaitThread() {   while(true)   {  // 等待缓冲区的通知消息   mNotificationEvent.WaitOne(Timeout.Infinite, true);   // 录制数据   RecordCapturedData();   } }/// <summary> /// 创建保存的波形文件,并写入必要的文件头. /// </summary> private void CreateSoundFile() {   /**************************************************************************  Here is where the file will be created. A  wave file is a RIFF file, which has chunks  of data that describe what the file contains.  A wave RIFF file is put together like this:
     The 12 byte RIFF chunk is constructed like this:  Bytes 0 - 3 : 'R' 'I' 'F' 'F' Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description.   (4 bytes for "WAVE" + 24 bytes for format chunk length +   8 bytes for data chunk description + actual sample data size.)   Bytes 8 - 11: 'W' 'A' 'V' 'E'
      The 24 byte FORMAT chunk is constructed like this:   Bytes 0 - 3 : 'f' 'm' 't' ' '   Bytes 4 - 7 : The format chunk length. This is always 16.  Bytes 8 - 9 : File padding. Always 1.   Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo.   Bytes 12- 15: Sample rate.   Bytes 16- 19: Number of bytes per second.   Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or   16 bit mono, 4 for 16 bit stereo.   Bytes 22- 23: Number of bits per sample.
      The DATA chunk is constructed like this:   Bytes 0 - 3 : 'd' 'a' 't' 'a'   Bytes 4 - 7 : Length of data, in bytes.   Bytes 8 -...: Actual sample data.   ***************************************************************************/   // Open up the wave file for writing.    mWaveFile = new FileStream(mFileName, FileMode.Create);   mWriter = new BinaryWriter(mWaveFile);
      // Set up file with RIFF chunk info.   char[] ChunkRiff = {'R','I','F','F'};   char[] ChunkType = {'W','A','V','E'};   char[] ChunkFmt = {'f','m','t',' '};   char[] ChunkData = {'d','a','t','a'};   short shPad = 1; // File padding   int nFormatChunkLength = 0x10; // Format chunk length.   int nLength = 0; // File length, minus first 8 bytes of RIFF description. This will be filled in later.   short shBytesPerSample = 0; // Bytes per sample.
      // 一个样本点的字节数目   if (8 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels)shBytesPerSample = 1;   else if ((8 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels) || (16 == mWavFormat.BitsPerSample && 1 == mWavFormat.Channels))   shBytesPerSample = 2;   else if (16 == mWavFormat.BitsPerSample && 2 == mWavFormat.Channels)   shBytesPerSample = 4;  // RIFF 块   mWriter.Write(ChunkRiff);   mWriter.Write(nLength);   mWriter.Write(ChunkType);
      // WAVE块   mWriter.Write(ChunkFmt);   mWriter.Write(nFormatChunkLength);   mWriter.Write(shPad);   mWriter.Write(mWavFormat.Channels);   mWriter.Write(mWavFormat.SamplesPerSecond);   mWriter.Write(mWavFormat.AverageBytesPerSecond);   mWriter.Write(shBytesPerSample);   mWriter.Write(mWavFormat.BitsPerSample);   // 数据块   mWriter.Write(ChunkData);  mWriter.Write((int)0); // The sample length will be written in later. }
      

  10.   

    5.外部窗体调用方式声明部分:private SoundRecord recorder = null; // 录音 窗体构造函数:recorder = new SoundRecord(); 启动录音按钮:private void btnStart_Click(object sender, System.EventArgs e) {   //   // 录音设置   //   string wavfile = null;   wavfile = “test.wav”;   recorder.SetFileName(wavfile);   recorder.RecStart(); } 中止录音按钮:private void btnStop_Click(object sender, System.EventArgs e) {  recorder.RecStop();   recorder = null;}
    6.需要添加的外部引用文件在系统的System32目录下添加以下两个引用文件,如果没有,在DirectX的开发包内可以找到。Microsoft.DirectX.dllMicrosoft.DirectX.DirectSound.dll  
      

  11.   


    谢谢你的代码,这个是 winform 用的代码,不是 b/s 架构,无法实现客户端调用。
      

  12.   

    flash录音 http://download.csdn.net/source/920673 希望对你有帮助
      

  13.   

    http://www.cnblogs.com/nasa/archive/2010/04/16/silvelight-AudioCapture.html
      

  14.   


    这个flash 下载以后有点问题,不能用,不过至少看到了希望,我还需要再找找,或者自己写个flash
      

  15.   

    我写了一个关于录音的 ActiveX 控件,但是加载到 asp.net 客户端页面上不显示,但是可以安装,不知道为什么,有高手指点一下吗?主要构成:
    1)UserControl 控件
       用vs2008 创建了一个录制语音的用户控件,并打包生成了 setup.exe 程序2)在 asp.net 工程的客户端页面中加载这个 ActiveX 控件<object id="record" classid="clsid:30D6443E-0367-4c84-BEDE-97F1BF7938C6" codebase="setup.exe" width="400" height="40"></object>3) 浏览这个客户端页面可以看到提示下载 ActiveX 控件,并安装成功,但是刷新时这个控件没有显示出来?
      

  16.   

    其实这个,可以用系统自带的,而且win7和XP的文件位置都一样,可以用javascript里面的方法来提取位置即可以,至于说到ActiveX,你点击允许就可以,让他弹出了,其实做成是winfrom的也好啊!
      

  17.   

    已经实现了,是用 Silverlight4.0 做的,你们可以参考一下Silverlight中音频视频部分的代码