技术背景
我们在做Windows平台RTMP推送、轻量级RTSP服务录像模块的时候,部分开发者抱怨路径无法设置中文,只能设置为英文。
以C#的接口为例,早期的设计如下:
/*
* 设置本地录像目录, 必须是英文目录,否则会失败
*/
[DllImport(@"SmartPublisherSDK.dll")]
public static extern UInt32 NT_PB_SetRecorderDirectory(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] String dir, IntPtr pReserve);
考虑到一些场景的特殊性,可能需要中文路径,我们设计的接口如下:
/*
* 设置本地录像目录, 支持中文目录, 需要设置宽字符,比如L"D:\\xxx\\gg"
*/
[DllImport(@"SmartPublisherSDK.dll")]
public static extern UInt32 NT_PB_SetRecorderDirectoryW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)]String dir, IntPtr pReserve);
调用如下,以调用开始录像、暂停录像、停止录像为例,调用逻辑如下,可以看到除了中文路径诉求,录像模块还可以添加前缀、添加文字、水印:
public bool StartRecorder()
{
if (is_empty_handle() || is_recording())
return false;
//string edit_rec_dir = "D:\\dntest";
string edit_rec_dir = "D:\\推送端录像";
if (String.IsNullOrEmpty(edit_rec_dir))
{
Console.WriteLine("请设置录像目录");
return false;
}
uint ret = NTSmartPublisherSDK.NT_PB_SetRecorderDirectoryW(handle_, edit_rec_dir, IntPtr.Zero);
if (NTBaseCodeDefine.NT_ERC_OK != ret)
{
try_close_handle();
return false;
}
uint rec_max_file_size = 512 * 1024;
NTSmartPublisherSDK.NT_PB_SetRecorderFileMaxSize(handle_, rec_max_file_size);
NT_PB_RecorderFileNameRuler rec_name_ruler = new NT_PB_RecorderFileNameRuler();
String rec_file_name_prefix_ = "transcode-rec";
rec_name_ruler.file_name_prefix_ = rec_file_name_prefix_.ToString();
rec_name_ruler.append_date_ = 1;
rec_name_ruler.append_time_ = 1;
NTSmartPublisherSDK.NT_PB_SetRecorderFileNameRuler(handle_, ref rec_name_ruler);
if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartRecorder(handle_, IntPtr.Zero))
{
try_close_handle();
return false;
}
shared_lock_.EnterWriteLock();
try
{
handle_reference_count_++;
is_recording_ = true;
}
finally
{
shared_lock_.ExitWriteLock();
}
return true;
}
public UInt32 PauseRecorder(bool is_pause)
{
if (is_empty_handle() || !is_recording())
return NTBaseCodeDefine.NT_ERC_FAILED;
UInt32 ret = NTBaseCodeDefine.NT_ERC_OK;
if (is_pause)
{
ret = NTSmartPublisherSDK.NT_PB_PauseRecorder(handle_, 1);
if ((UInt32)NT.NTSmartPublisherDefine.NT_PB_E_ERROR_CODE.NT_ERC_PB_NEED_RETRY == ret)
{
Console.WriteLine("暂停录像失败, 请重新尝试!");
return ret;
}
else if (NTBaseCodeDefine.NT_ERC_OK == ret)
{
//btn_pause_rec.Text = "恢复录像";
}
}
else
{
ret = NTSmartPublisherSDK.NT_PB_PauseRecorder(handle_, 0);
if ((UInt32)NT.NTSmartPublisherDefine.NT_PB_E_ERROR_CODE.NT_ERC_PB_NEED_RETRY == ret)
{
Console.WriteLine("恢复录像失败, 请重新尝试!");
return ret;
}
else if (NTBaseCodeDefine.NT_ERC_OK == ret)
{
//btn_pause_rec.Text = "暂停录像";
}
}
return ret;
}
public void StopRecorder()
{
if (is_empty_handle() || !is_recording())
return;
shared_lock_.EnterWriteLock();
try
{
is_recording_ = false;
handle_reference_count_--;
}
finally
{
shared_lock_.ExitWriteLock();
}
NTSmartPublisherSDK.NT_PB_StopRecorder(handle_);
try_close_handle();
}
开始录像和录像完成后,提示如下:
private void PbEventCallBack(UInt32 event_id,
Int64 param1,
Int64 param2,
UInt64 param3,
UInt64 param4,
[MarshalAs(UnmanagedType.LPStr)] String param5,
[MarshalAs(UnmanagedType.LPStr)] String param6,
IntPtr param7)
{
String event_log = "";
switch (event_id)
{
......
case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_RECORDER_START_NEW_FILE:
event_log = " start new recorder file";
byte[] utf8_bytes = Encoding.Default.GetBytes(param5);
byte[] default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8_bytes);
String file_name = Encoding.Default.GetString(default_bytes);
if (!String.IsNullOrEmpty(file_name))
{
event_log = event_log + " file name:" + file_name;
}
break;
case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_ONE_RECORDER_FILE_FINISHED:
event_log = " finish recorder file";
byte[] finished_utf8_bytes = Encoding.Default.GetBytes(param5);
byte[] finished_default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, finished_utf8_bytes);
String finished_file_name = Encoding.Default.GetString(finished_default_bytes);
if (!String.IsNullOrEmpty(finished_file_name))
{
event_log = event_log + " file name:" + finished_file_name;
}
break;
.......
default:
break;
}
EventGetPublisherEventMsg(event_log);
}
总结
Windows平台RTMP推送、轻量级RTSP服务配套的录像模块,除了设置录像保存路径外、还可以设置录像文件前缀、是不是添加日期、时间等,还有就是单个录像文件大小,超过这个大小后,会自动切换到下个文件。