Пример librtmp c программированием?

Привет, ребята, я новичок в программировании на C и хотел бы знать, есть ли у кого-нибудь действительно простой пример открытия файла .flv и отправки на сервер wowza с помощью librtmp.

Я нашел много кода, который можно подключить с помощью библиотеки, но не так много при публикации flv.

В основном:

init librtmp -> включить запись -> подключить -> пакетировать flv -> отправлять пакеты до завершения

РЕДАКТИРОВАТЬ:

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

https://github.com/noirotm/flvmeta/blob/master/src/flv.c


person Adrian M Cavazos    schedule 15.07.2014    source источник


Ответы (2)


Это автор FLVMeta здесь.

Возможно, вы захотите взглянуть на мой ответ на этот вопрос: https://stackoverflow.com/a/13803143/393701

В дополнение к этой информации я могу объяснить некоторые части программного обеспечения C++, которое я написал (к сожалению, на данный момент не с открытым исходным кодом), которые предназначены для потоковой передачи файлов FLV на сервер RTMP.

Это было протестировано и отлично работает с Wowza, nginx-rtmp, а также с сервером прямой трансляции Dailymotion.

Инициализация

std::string rtmp_url = "rtmp://server/app/stream";
// add this if doing live streaming:
rtmp_url.append(" live=1");

RTMP * rtmp = RTMP_Alloc();
if (!rtmp) {
    std::cerr << "Unable to create rtmp object\n";
    return;
}

RTMP_Init(rtmp);
RTMP_LogSetLevel(RTMP_LOGINFO);
RTMP_LogSetOutput(stderr);
RTMP_SetupURL(rtmp, const_cast<char*>(rtmp_url.c_str())); // librtmp is a mess
RTMP_EnableWrite(rtmp);

Странный const_cast связан с тем, что librtmp был странно разработан и использует неконстантный char * в качестве URL-адреса, даже если он не может быть изменен библиотекой на самом деле.
Кроме того, буфер будет использоваться для as пока существует объект RTMP, поэтому строку нельзя освобождать перед удалением объекта RTMP.

Подключение

// connect to server
if (!RTMP_Connect(rtmp, NULL)) {
    std::cerr << "Unable to connect to server\n";
    RTMP_Free(rtmp);
    return;
}

Второй аргумент RTMP_Connect — это необязательный указатель на пакет RTMP, который следует отправлять в качестве параметра соединения вместо пакета соединения по умолчанию, отправляемого librtmp. Обычно это не следует использовать при подключении к «обычным» RTMP-серверам.

// connect to stream (this will be the stream specified in the RTMP URL)
if (!RTMP_ConnectStream(rtmp, 0)) {
    cerr << "Unable to connect to stream\n";
    RTMP_Free(rtmp);
    return;
}

Второй аргумент RTMP_ConnectStream — это целое число, представляющее отметку времени, к которой следует обращаться при воспроизведении видео. При публикации использование 0 является беспроигрышным вариантом.

Публикация пакетов

В этом разделе предполагается использование кода FLV из проекта FLVMeta (см. https://github.com/noirotm/flvmeta/blob/master/src/flv.h#L175).

flv_stream * flvin = flv_open(input_file.c_str());
if (!flvin) {
    std::cerr << "Unable to open " << input_file << '\n';
    return;
}

Во-первых, рекомендуется убедиться, что мы открыли настоящий FLV-файл.

flv_header header;
int res = flv_read_header(flvin, &header);
if (res == FLV_ERROR_NO_FLV || res == FLV_ERROR_EOF) {
    std::cerr << "Input file is not an FLV video\n";
    flv_close(flvin);
    return;
}

Теперь прочитайте каждый тег в файле и отправьте их на RTMP-сервер.

// 10 MB copy buffer should be enough
#define BUFFER_SIZE 10000000
char buffer[BUFFER_SIZE];

flv_tag tag;
while (flv_read_tag(flvin, &tag) != FLV_ERROR_EOF) {
    // copy tag header
    flv_copy_tag(buffer, &tag, FLVSTREAMER_BUFFER_SIZE);

    // copy tag body
    size_t data_size = flv_read_tag_body(flvin, buffer + FLV_TAG_SIZE, BUFFER_SIZE - FLV_TAG_SIZE);

    // copy previous tag size
    uint32 pts;
    flv_read_prev_tag_size(flvin, &pts);
    flv_copy_prev_tag_size(
        buffer + FLV_TAG_SIZE + flv_tag_get_body_length(tag),
        pts,
        BUFFER_SIZE - (FLV_TAG_SIZE + flv_tag_get_body_length(tag))
    );

    // write the packet
    int size = FLV_TAG_SIZE + data_size + sizeof(uint32);
    if (RTMP_Write(rtmp, buffer, size) <= 0) {
        std::cerr << "Unable to write to server" << endl;
        break;
    }
}

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

Также важно отметить, что нельзя отправлять заголовок файла FLV. librtmp обнаружит любую попытку отправить заголовок FLV и предотвратит ее.

Не обязательно читать входящие RTMP-пакеты во время публикации, но если вы хотите правильно обрабатывать протокол, рекомендуется подход, используемый @szatmary в его коде.

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

Убираться

flv_close(flvin);
RTMP_Free(rtmp);

Функция RTMP_Free позаботится о закрытии потока, соединения и освобождении выделенной памяти.

person SirDarius    schedule 10.08.2014
comment
Большое спасибо, я искал код c, но объяснение работает, теперь я на правильном пути :) - person Adrian M Cavazos; 12.08.2014
comment
@SirDarius Я ищу пример RTMP-сервера, как он работает с вашим приведенным выше кодом клиента cpp? - person AJit; 18.03.2018
comment
@AJit Похоже, это не входит в рамки этого вопроса. Хотите написать RTMP-сервер с нуля? librtmp — это только клиентская библиотека. - person SirDarius; 28.03.2018
comment
Да @SirDarius, в итоге я подключился и транслировал через FFMPEG. - person AJit; 29.03.2018

Вот очень простой пример, который я написал на C++ https://github.com/szatmary/RtmpBroadcaster/blob/master/rtmp.cpp

person szatmary    schedule 15.07.2014
comment
как бы вы открыли файл flv и использовали эту функцию? sendTag(FlvTag &tag) - person Adrian M Cavazos; 15.07.2014
comment
Посмотрите остальную часть проекта RtmpBroadcaster на git hub. Это комплексное решение. - person szatmary; 15.07.2014
comment
Спасибо за ответ на мой вопрос, не могли бы вы указать мне правильное направление, глядя на ваш код, я думаю, мне нужно сначала ознакомиться с flv и узнать, как читать структуру данных, чтобы использовать ее с librtmp. Я прав? у вас есть какой-нибудь URL или с чего начать? - person Adrian M Cavazos; 15.07.2014
comment
adobe.com/content/dam/Adobe/ ru/devnet/flv/pdfs/ - person szatmary; 15.07.2014