Bass.net调用DOWNLOADPROC仅录制5秒,如何实现长时间录制?
解决Bass.net录制网络音频流仅5秒的问题
我来帮你排查下这个问题——你的代码只能录制5秒,核心原因是主线程执行完Main方法就直接退出了!BASS的网络流下载是异步处理的,依赖程序保持运行状态才能持续接收音频数据。当主线程结束,整个程序就终止了,录制自然就停了。
问题代码的核心缺陷
你的Main方法里,创建完音频流后没有任何阻塞逻辑,程序瞬间就执行完毕退出了,异步的下载回调还没来得及接收更多数据就被终止了。
修改方案:让主线程保持运行并支持主动停止
我们需要给程序添加一个等待机制,让主线程一直运行到用户主动触发停止,同时正确清理资源。以下是修改后的完整代码:
using System; using System.IO; using System.Runtime.InteropServices; using Un4seen.Bass; class Program { private static FileStream _fs = null; private static DOWNLOADPROC _myDownloadProc; private static byte[] _data; private static int _streamHandle = 0; // 保存流句柄,用于后续停止 static void Main(string[] args) { // 初始化BASS时检查是否成功 if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)) { Console.WriteLine("BASS初始化失败:" + Bass.BASS_ErrorGetCode()); return; } _myDownloadProc = new DOWNLOADPROC(MyDownload); // 创建网络音频流,注意保留句柄 _streamHandle = Bass.BASS_StreamCreateURL( "http://m2.fabricahost.com.br:8704/;stream.mp3", 0, BASSFlag.BASS_STREAM_BLOCK | BASSFlag.BASS_SAMPLE_MONO | BASSFlag.BASS_STREAM_STATUS, _myDownloadProc, IntPtr.Zero ); if (_streamHandle == 0) { Console.WriteLine("创建音频流失败:" + Bass.BASS_ErrorGetCode()); Bass.BASS_Fini(); return; } Console.WriteLine("录制已开始,按任意键停止..."); Console.ReadLine(); // 阻塞主线程,等待用户输入 // 主动停止流,触发下载回调的结束逻辑 Bass.BASS_StreamFree(_streamHandle); // 清理BASS资源 Bass.BASS_Fini(); Console.WriteLine("录制已完成,文件已保存为output.mp3"); } private static void MyDownload(IntPtr buffer, int length, IntPtr user) { try { if (buffer == IntPtr.Zero) { // 流结束,关闭文件 Console.WriteLine("音频流已结束"); _fs?.Flush(); _fs?.Close(); _fs = null; return; } if (_fs == null) { // 首次收到数据,创建文件 _fs = File.OpenWrite("output.mp3"); Console.WriteLine("开始写入文件..."); } // 动态调整数据缓冲区大小 if (_data == null || _data.Length < length) _data = new byte[length]; // 从非托管内存复制到托管数组 Marshal.Copy(buffer, _data, 0, length); // 写入文件 _fs.Write(_data, 0, length); } catch (Exception ex) { Console.WriteLine("录制过程中发生错误:" + ex.Message); // 出错时清理资源 _fs?.Close(); Bass.BASS_StreamFree(_streamHandle); Bass.BASS_Fini(); } } }
关键修改点说明
- 主线程阻塞:添加
Console.ReadLine()让程序保持运行,直到用户按下任意键停止录制。 - 保存流句柄:新增
_streamHandle变量保存创建的流句柄,用于后续主动停止流。 - 错误处理:添加BASS初始化和流创建的失败检查,以及录制过程中的异常捕获,避免程序崩溃。
- 资源清理:主动调用
BASS_StreamFree停止流,触发回调的结束逻辑,确保文件正确关闭;最后调用BASS_Fini清理BASS的系统资源。
额外注意事项
- 确保你引用的Bass.net版本与系统架构匹配(x86/x64),否则可能出现初始化失败或异常。
BASS_STREAM_BLOCK标志确保数据块完整后再触发回调,避免写入不完整的音频数据。- 如果需要长时间录制,可以考虑添加后台线程处理,或者使用定时器检查录制时长,自动停止。
内容的提问来源于stack exchange,提问作者kozima




