Когда многие разработчики обменивались со мной техническими вопросами, они говорили, что особенность использования модуля Daniu Live SDK заключается в том, что если вы думаете о какой-либо функции, вы почти можете найти соответствующую реализацию в заголовочных файлах и демо-версиях. Как вы собрали так много? технические требования?
На самом деле, это зависит от нашей многолетней репутации в отрасли и масштабного накопления реальных пользователей, что позволяет нам четко понимать, что необходимо включить в модуль прямой трансляции, а от чего следует отказаться.
В этой статье в качестве примера используется конструкция функций прямой трансляции и записи RTSP | RTMP платформы Windows Daniu Live SDK, чтобы поговорить о детальном дизайне нашего интерфейса.
В настоящее время наш модуль видеозаписи охватывает push-конец Windows/Linux/android/iOS (включая облегченный сервисный модуль RTSP, модуль потоковой передачи RTMP и модуль доступа к устройству GB28181) и конец воспроизведения RTSP | RTMP. Он в основном реализует следующие функции:
Настройте запись только видео или аудио:
/*
* Установите, записывать ли видео. По умолчанию, если в источнике видео есть видео, оно будет записано. Если видео нет, оно не будет записано. Но в некоторых сценариях вы можете не захотеть записывать видео, а записывать только звук, поэтому добавьте переключатель.
*
* is_record_video: 1 означает запись видео, 0 Указывает на отсутствие записи видео, По умолчанию – 1.
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderVideo(IntPtr handle, Int32 is_record_video);
/*
* Установите, записывать ли звук. По умолчанию, если источник видео имеет звук, он будет записан. Если нет, он не будет записан. Но в некоторых сценариях вы можете не захотеть записывать звук, а записывать только видео, поэтому добавьте переключатель.
*
* is_record_audio: 1 означает запись звука, 0 Указывает на отсутствие записи звука, По умолчанию – 1.
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderAudio(IntPtr handle, Int32 is_record_audio);
Настройки места хранения видео,Установить локальный каталог записи,Следует отметить, что,у нас естьПоддержка настройки пути на китайском языке с широкими символами,Начать запись и завершить запись,У нас будут обратные вызовы событий:
/*
* Установите локальный каталог записи, Поддержка китайского каталога, Необходимо задать широкие символы, например L"D:\\xxx\\gg"
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderDirectoryW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] String dir);
Установите размер одного видеофайла. Если он всегда находится в режиме записи, то при превышении этого размера он будет автоматически разделен на следующий файл:
/*
* Установите максимальный размер одного видеофайла, При превышении этого значения он будет разрезан на второй файл.
* size: Единица измерения: КБ (1024 байт). Текущая сфера применения [5MB-800MB], вне диапазона будет установлено в пределах диапазона
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderFileMaxSize(IntPtr handle, UInt32 size);
Установите правила генерации названия видео:
/*
* Установите правила создания имени видеофайла
*/
[DllImport(@"SmartPlayerSDK.dll", EntryPoint = "NT_SP_SetRecorderFileNameRuler", CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 NT_SP_SetRecorderFileNameRuler(IntPtr handle, ref NT_SP_RecorderFileNameRuler ruler);
Структура определяется следующим образом:
/*Если все три элемента равны 0, запись не начнется*/
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NT_SP_RecorderFileNameRuler
{
public UInt32 type_; // В настоящее время это значение по умолчанию равно 0 и будет расширено в будущем.
[MarshalAs(UnmanagedType.LPStr)] public String file_name_prefix_; // Установите префикс имени видеофайла, Например: даниулив
public Int32 append_date_; // Если оно равно 1, к имени файла будет добавлена дата. Например: даниулив-2017-01-17
public Int32 append_time_; // Если это 1,добавит время,Например: даниулив-2017-01-17-17-10-36
}
Для начала и завершения записи у нас есть обратные вызовы событий. Интерфейс обратного вызова настроен следующим образом:
/*
* Установите интерфейс обратного видеозвонка
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderCallBack(IntPtr handle,
IntPtr call_back_data, SP_SDKRecorderCallBack call_back);
Устанавливаем переключатель конвертации звука в кодировку AAC во время записи. Учитывая, что AAC более универсален, добавляем функцию конвертации других кодировок звука (таких как speex, pcmu, pcma и т.д.) в AAC:
/*
* Установите переключатель для преобразования звука в кодировку AAC при записи, aac является более общим, а SDK добавляет другие кодировки звука (например, speex, pcmu, pcma и т. д.) в функцию aac.
* is_transcode: Если установлено значение 1, то если кодировка звука не aac, она будет преобразована в aac. Если это aac, преобразование выполняться не будет. Если установлено значение 0, преобразование выполняться не будет. Значение по умолчанию — 0.
* Уведомление: Транскодирование увеличит потребление производительности
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_SetRecorderAudioTranscodeAAC(IntPtr handle, Int32 is_transcode);
Интерфейс управления видео, начало и завершение записи:
/*
* Начать запись
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_StartRecorder(IntPtr handle);
/*
* Остановить запись
*/
[DllImport(@"SmartPlayerSDK.dll")]
public static extern UInt32 NT_SP_StopRecorder(IntPtr handle);
Взяв в качестве примера демо-версию C#, давайте посмотрим на пример кода видеовызова:
Установите правила записи:
private void btn_record_config_Click(object sender, EventArgs e)
{
RecordConfigForm record_config_dlg = new RecordConfigForm(is_rec_video_, is_rec_audio_, rec_dir_, rec_name_file_prefix_, max_file_size_, is_append_date_, is_append_time_, is_audio_transcode_aac_);
record_config_dlg.ShowDialog();
String rec_dir = record_config_dlg.RecDir();
if (!String.IsNullOrEmpty(rec_dir))
{
rec_dir_ = rec_dir;
}
else
{
MessageBox.Show("Путь сохранения видео не задан, по умолчанию оно сохраняется в папке записи..");
}
is_rec_video_ = record_config_dlg.IsRecVideo();
is_rec_audio_ = record_config_dlg.IsRecAudio();
rec_name_file_prefix_ = record_config_dlg.RecNameFilePrefix();
max_file_size_ = record_config_dlg.MaxFileSize();
is_append_date_ = record_config_dlg.IsAppendDate();
is_append_time_ = record_config_dlg.IsAppendTime();
is_audio_transcode_aac_ = record_config_dlg.IsAudioTanscodeAAC();
}
Начать запись и завершить запись:
private void btn_record_Click(object sender, EventArgs e)
{
if (player_handle_ == IntPtr.Zero)
return;
if (btn_record.Text == "видео")
{
if (!is_rec_video_ && !is_rec_audio_)
{
MessageBox.Show("Необходимо выбрать хотя бы один из параметров аудиозаписи и видеозаписи!");
return;
}
if (!is_playing_)
{
if (!InitCommonSDKParam())
{
MessageBox.Show("Неверная настройка параметра!");
return;
}
}
NTSmartPlayerSDK.NT_SP_SetRecorderVideo(player_handle_, is_rec_video_ ? 1 : 0);
NTSmartPlayerSDK.NT_SP_SetRecorderAudio(player_handle_, is_rec_audio_ ? 1 : 0);
UInt32 ret = NTSmartPlayerSDK.NT_SP_SetRecorderDirectoryW(player_handle_, rec_dir_);
if (NT.NTBaseCodeDefine.NT_ERC_OK != ret)
{
MessageBox.Show("Не удалось установить каталог записи");
return;
}
NTSmartPlayerSDK.NT_SP_SetRecorderFileMaxSize(player_handle_, max_file_size_);
NT_SP_RecorderFileNameRuler rec_name_ruler = new NT_SP_RecorderFileNameRuler();
rec_name_ruler.type_ = 0;
rec_name_ruler.file_name_prefix_ = rec_name_file_prefix_;
rec_name_ruler.append_date_ = is_append_date_ ? 1 : 0;
rec_name_ruler.append_time_ = is_append_time_ ? 1 : 0;
NTSmartPlayerSDK.NT_SP_SetRecorderFileNameRuler(player_handle_, ref rec_name_ruler);
record_call_back_ = new SP_SDKRecorderCallBack(SDKRecorderCallBack);
NTSmartPlayerSDK.NT_SP_SetRecorderCallBack(player_handle_, IntPtr.Zero, record_call_back_);
NTSmartPlayerSDK.NT_SP_SetRecorderAudioTranscodeAAC(player_handle_, is_audio_transcode_aac_ ? 1 : 0);
if (NT.NTBaseCodeDefine.NT_ERC_OK != NTSmartPlayerSDK.NT_SP_StartRecorder(player_handle_))
{
MessageBox.Show("Запись не удалась!");
return;
}
btn_record.Text = "Остановить запись";
is_recording_ = true;
}
else
{
StopRecorder();
}
}
Для обработки обратного вызова видео, поскольку мы поддерживаем пути на китайском языке с широкими символами, путь к файлу, возвращающийся из обратного вызова, необходимо обрабатывать просто:
private void RecordCallBack(UInt32 status, [MarshalAs(UnmanagedType.LPStr)] String file_name)
{
byte[] utf8_bytes = Encoding.Default.GetBytes(file_name);
byte[] default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8_bytes);
String recorder_file_name = Encoding.Default.GetString(default_bytes);
StringBuilder sb = new StringBuilder();
sb.Append("Состояние записи:");
if (status == 1)
{
sb.Append("new file: ");
}
else if(status == 2)
{
sb.Append("finished file: ");
}
sb.Append(recorder_file_name);
MessageBox.Show(sb.ToString());
}
Выше приведено обсуждение дизайна интерфейса, связанного с записью прямых трансляций RTSP | RTMP на платформе Windows. Заинтересованные разработчики могут связаться со мной индивидуально. Некоторые говорят, что в домашней интернет-среде действительно сложно выжить SDK. Да, их так много с открытым исходным кодом, почему я должен использовать ваш? Но некоторые люди говорят, что многие традиционные отрасли в настоящее время предъявляют очень высокие технические требования к потоковому вещанию, и найти надежный вариант на рынке действительно сложно. Сосредоточьтесь на чем-то одном, делайте что-то очень хорошо и достигайте одного с репутацией, быстрее, чем скорость, что делает плеер прямой трансляции RTSP | RTMP более подходящим для сценариев использования с высокими требованиями к задержке (например, контроль баланса, дроны и т. д.). ), интеллектуальные роботы и т. д.), это наше постоянное стремление.