Как RTSP | RTMP-плеер платформы Windows реализует детальное управление записью видео?
Как RTSP | RTMP-плеер платформы Windows реализует детальное управление записью видео?

Технический бэкграунд

Когда многие разработчики обменивались со мной техническими вопросами, они говорили, что особенность использования модуля Daniu Live SDK заключается в том, что если вы думаете о какой-либо функции, вы почти можете найти соответствующую реализацию в заголовочных файлах и демо-версиях. Как вы собрали так много? технические требования?

На самом деле, это зависит от нашей многолетней репутации в отрасли и масштабного накопления реальных пользователей, что позволяет нам четко понимать, что нужно модулю прямой трансляции, а от чего нужно отказаться.

Технический проект

В этой статье в качестве примера используется конструкция функций прямой трансляции и записи RTSP | RTMP платформы Windows Daniu Live SDK, чтобы поговорить о детальном дизайне нашего интерфейса.

В настоящее время наш модуль видеозаписи охватывает push-конец Windows/Linux/android/iOS (включая облегченный сервисный модуль RTSP, модуль потоковой передачи RTMP и модуль доступа к устройству GB28181) и конец воспроизведения RTSP | RTMP. Он в основном реализует следующие функции:

  • [Pull Streaming] Поддержка получения потокового видео RTSP;
  • [Pull Streaming] Поддержка извлечения записей потока RTMP;
  • [Запись в режиме push-end] Поддерживает одновременную запись RTMP|RTSP в режиме push-end;
  • [Упрощенная запись службы RTSP] Поддерживает синхронизированную запись с помощью облегченного SDK службы RTSP;
  • [Пауза/возобновление записи в режиме реального времени] Поддерживает паузу и возобновление записи в реальном времени во время записи на стороне подачи;
  • [Логическое разделение] Daniu Live Recording SDK отличается от обычных интерфейсов записи, более интеллектуален и полностью отделен от push, воспроизведения, пересылки и встроенных облегченных функций SDK службы RTSP, поддерживающих запись в любое время;
  • [переключение URL-адресов] Во время процесса записи поддерживается переключение между разными URL-адресами. Если две конфигурации URL-адресов согласованы, можно записать один и тот же файл MP4. Если они несовместимы, его можно автоматически разделить на следующий файл.
  • [Настройки параметров] Поддерживает настройку размера одного файла записи, пути записи и т. д., а также поддерживает режимы записи чистого звука, чистого видео, а также аудио и видео;
  • [Транскокодирование аудио] Поддержка преобразования звука (PCMU/PCMA, Speex и т. д.) в AAC перед записью;
  • [Поддержка 265] Поддержка записи RTSP/RTMP H.265 в файлы MP4;
  • [Запись Push End 265] Push End SDK поддерживает запись H265;
  • [Стыковка и запись данных с внешним кодированием на push-конце] Поддерживает стыковку и запись данных с внешним кодированием на push-конце (H.264/AAC);
  • [Обратный вызов по событию] Имеются обратные вызовы по событиям от начала записи до конца записи. Перегрузка сети, а также синхронизация аудио и видео обрабатываются очень удобно.

Настройте запись только видео или аудио:

Язык кода:csharp
копировать
        /*
		 * Установите, записывать ли видео. По умолчанию, если в источнике видео есть видео, оно будет записано. Если видео нет, оно не будет записано. Но в некоторых сценариях вы можете не захотеть записывать видео, а записывать только звук, поэтому добавьте переключатель.
         * 
		 * 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);

Настройки места хранения видео,Установить локальный каталог записи,Следует отметить, что,у нас естьПоддержка настройки пути на китайском языке с широкими символами,Начать запись и завершить запись,У нас будут обратные вызовы событий:

Язык кода:csharp
копировать
        /*
		 * Установите локальный каталог записи, Поддержка китайского каталога, Необходимо задать широкие символы, например L"D:\\xxx\\gg"
		 */
        [DllImport(@"SmartPlayerSDK.dll")]
        public static extern UInt32 NT_SP_SetRecorderDirectoryW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)] String dir);

Установите размер одного видеофайла. Если он всегда находится в режиме записи, то при превышении этого размера он будет автоматически разделен на следующий файл:

Язык кода:csharp
копировать
		/*
		 * Установите максимальный размер одного видеофайла, При превышении этого значения он будет разрезан на второй файл.
		 * size: Единица измерения: КБ (1024 байт). Текущая сфера применения [5MB-800MB], вне диапазона будет установлено в пределах диапазона
		 */
        [DllImport(@"SmartPlayerSDK.dll")]
        public static extern UInt32 NT_SP_SetRecorderFileMaxSize(IntPtr handle, UInt32 size);

Установите правила генерации названия видео:

Язык кода:csharp
копировать
		/*
		 * Установите правила создания имени видеофайла
		 */
        [DllImport(@"SmartPlayerSDK.dll", EntryPoint = "NT_SP_SetRecorderFileNameRuler", CallingConvention = CallingConvention.StdCall)]
        public static extern UInt32 NT_SP_SetRecorderFileNameRuler(IntPtr handle, ref NT_SP_RecorderFileNameRuler ruler);

Структура определяется следующим образом:

Язык кода:csharp
копировать
    /*Если все три элемента равны 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
    }

Для начала и завершения записи у нас есть обратные вызовы событий. Интерфейс обратного вызова настроен следующим образом:

Язык кода:csharp
копировать
		/*
		 * Установите интерфейс обратного видеозвонка
		 */
        [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:

Язык кода:csharp
копировать
        /*
         * Установите переключатель для преобразования звука в кодировку 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);

Интерфейс управления видео, начало и завершение записи:

Язык кода:csharp
копировать
		/*
		 * Начать запись
		 */
        [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#, давайте посмотрим на пример кода видеовызова:

Установите правила записи:

Язык кода:csharp
копировать
        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();
        }

Начать запись и завершить запись:

Язык кода:csharp
копировать
        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();
            }
        }

Обработка обратного вызова видео: поскольку мы поддерживаем пути на китайском языке с широкими символами, путь к файлу, полученный в результате обратного вызова, требует простой обработки:

Язык кода:csharp
копировать
        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 более подходящим для сценариев использования с высокими требованиями к задержке (например, контроль баланса, дроны и т. д.). ), интеллектуальные роботы и т. д.), это наше постоянное стремление.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.