Broadcaster展示用http创建Transport进行推拉流,不需要websocket。
- 不需要信令,ffmpeg,gstreamer等就能直接接入。
- 不一定需要摄像头麦克风,纯音视频帧就能接入。
void Broadcaster::CreateSendTransport(bool enableAudio, bool useSimulcast)
{
std::cout << "[INFO] creating mediasoup send WebRtcTransport..." << std::endl;
json sctpCapabilities = this->device.GetSctpCapabilities();
/* clang-format off */
json body =
{
{ "type", "webrtc" },
{ "rtcpMux", true },
{ "sctpCapabilities", sctpCapabilities }
};
/* clang-format on */
auto r = cpr::PostAsync(
cpr::Url{ this->baseUrl + "/broadcasters/" + this->id + "/transports" },
cpr::Body{ body.dump() },
cpr::Header{ { "Content-Type", "application/json" } },
cpr::VerifySsl{ verifySsl })
.get();
if (r.status_code != 200)
{
std::cerr << "[ERROR] unable to create send mediasoup WebRtcTransport"
<< " [status code:" << r.status_code << ", body:\"" << r.text << "\"]" << std::endl;
return;
}
...
//MEDIA_FILE是一个本地文件,rtp://xxx就是plainTransport的推流地址地址
ffmpeg \
-re \
-v info \
-stream_loop -1 \
-i ${MEDIA_FILE} \
-map 0:a:0 \
-acodec libopus -ab 128k -ac 2 -ar 48000 \
-map 0:v:0 \
-pix_fmt yuv420p -c:v libvpx -b:v 1000k -deadline realtime -cpu-used 4 \
-f tee \
"[select=a:f=rtp:ssrc=${AUDIO_SSRC}:payload_type=${AUDIO_PT}]rtp://${audioTransportIp}:${audioTransportPort}?rtcpport=${audioTransportRtcpPort}|[select=v:f=rtp:ssrc=${VIDEO_SSRC}:payload_type=${VIDEO_PT}]rtp://${videoTransportIp}:${videoTransportPort}?rtcpport=${videoTransportRtcpPort}"
这里假设每1个PlainRtpTransport对应1路推流或者拉流
这里假设每1个PlainRtpTransport对应1路推流或者拉流
参考实现https://blog.csdn.net/weixin_29405665/article/details/111994983
function show_usage() { echo echo “USAGE” echo “—–” echo echo “ SERVER_URL=https://my.mediasoup-demo.org:4443 ROOM_ID=test MEDIA_FILE=./test.mp4 ./ffmpeg.sh” echo echo “ where:” echo “ - SERVER_URL is the URL of the mediasoup-demo API server” echo “ - ROOM_ID is the id of the mediasoup-demo room (it must exist in advance)” echo “ - MEDIA_FILE is the path to a audio+video file (such as a .mp4 file)” echo echo “REQUIREMENTS” echo “————” echo echo “ - ffmpeg: stream audio and video (https://www.ffmpeg.org)” echo “ - httpie: command line HTTP client (https://httpie.org)” echo “ - jq: command-line JSON processor (https://stedolan.github.io/jq)” echo }
echo
SERVER_URL=https://127.0.0.1:4443 ROOM_ID=1 MEDIA_FILE=H:/video/视频测试样例视频bipbop/bipbop-baseline.mp4 if [ -z “${SERVER_URL}” ] ; then >&2 echo “ERROR: missing SERVER_URL environment variable” show_usage exit 1 fi
if [ -z “${ROOM_ID}” ] ; then >&2 echo “ERROR: missing ROOM_ID environment variable” show_usage exit 1 fi
if [ -z “${MEDIA_FILE}” ] ; then >&2 echo “ERROR: missing MEDIA_FILE environment variable” show_usage exit 1 fi
if [ “$(command -v ffmpeg)” == “” ] ; then >&2 echo “ERROR: ffmpeg command not found, must install FFmpeg” show_usage exit 1 fi
if [ “$(command -v http)” == “” ] ; then >&2 echo “ERROR: http command not found, must install httpie” show_usage exit 1 fi
if [ “$(command -v jq)” == “” ] ; then >&2 echo “ERROR: jq command not found, must install jq” show_usage exit 1 fi
set -e
BROADCASTER_ID=$(LC_CTYPE=C tr -dc A-Za-z0-9 < /dev/urandom | fold -w ${1:-32} | head -n 1) HTTPIE_COMMAND=”http –check-status –verify no” AUDIO_SSRC=1111 AUDIO_PT=100 VIDEO_SSRC=2222 VIDEO_PT=102
#
# echo “»> verifying that room ‘${ROOM_ID}’ exists…”
${HTTPIE_COMMAND}
GET ${SERVER_URL}/rooms/${ROOM_ID} > /dev/null
#
# echo “»> creating Broadcaster…”
${HTTPIE_COMMAND}
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters
id=”${BROADCASTER_ID}”
displayName=”Broadcaster”
device:=’{“name”: “FFmpeg”}’
> /dev/null
#
# trap ‘echo “»> script exited with status code $?”; ${HTTPIE_COMMAND} DELETE ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID} > /dev/null’ EXIT
#
# echo “»> creating mediasoup PlainTransport for producing audio…”
res=$(${HTTPIE_COMMAND}
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID}/transports
type=”plain”
comedia:=true
rtcpMux:=false
2> /dev/null)
#
# eval “$(echo ${res} | jq -r ‘@sh “audioTransportId=(.id) audioTransportIp=(.ip) audioTransportPort=(.port) audioTransportRtcpPort=(.rtcpPort)”’)”
#
# echo “»> creating mediasoup PlainTransport for producing video…”
res=$(${HTTPIE_COMMAND}
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID}/transports
type=”plain”
comedia:=true
rtcpMux:=false
2> /dev/null)
#
# eval “$(echo ${res} | jq -r ‘@sh “videoTransportId=(.id) videoTransportIp=(.ip) videoTransportPort=(.port) videoTransportRtcpPort=(.rtcpPort)”’)”
#
# echo “»> creating mediasoup audio Producer…”
${HTTPIE_COMMAND} -v
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID}/transports/${audioTransportId}/producers
kind=”audio”
rtpParameters:=”{ "codecs": [{ "mimeType":"audio/opus", "payloadType":${AUDIO_PT}, "clockRate":48000, "channels":2, "parameters":{ "sprop-stereo":1 } }], "encodings": [{ "ssrc":${AUDIO_SSRC} }] }”
> /dev/null
#
# echo “»> creating mediasoup video Producer…”
${HTTPIE_COMMAND} -v
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID}/transports/${videoTransportId}/producers
kind=”video”
rtpParameters:=”{ "codecs": [{ "mimeType":"video/H264", "payloadType":${VIDEO_PT}, "clockRate":90000, "parameters":{ "packetization-mode":1, "profile-level-id":"42e01f"} }], "encodings": [{ "ssrc":${VIDEO_SSRC} }] }”
> /dev/null
#
# echo “»> running ffmpeg…”
#
#
ffmpeg
-re
-v info
-stream_loop -1
-i ${MEDIA_FILE}
-map 0:a:0
-acodec libopus -ab 128k -ac 2 -ar 48000
-map 0:v:0
-pix_fmt yuv420p -c:v libx264 -b:v 1000k -deadline realtime -cpu-used 4
-f tee
“[select=a:f=rtp:ssrc=${AUDIO_SSRC}:payload_type=${AUDIO_PT}]rtp://${audioTransportIp}:${audioTransportPort}?rtcpport=${audioTransportRtcpPort}|[select=v:f=rtp:ssrc=${VIDEO_SSRC}:payload_type=${VIDEO_PT}]rtp://${videoTransportIp}:${videoTransportPort}?rtcpport=${videoTransportRtcpPort}”
```