-
-
Notifications
You must be signed in to change notification settings - Fork 619
/
Copy pathffmpeg.sh
executable file
·189 lines (162 loc) · 5.77 KB
/
ffmpeg.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env bash
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
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"
AUDIO_SSRC=1111
AUDIO_PT=100
VIDEO_SSRC=2222
VIDEO_PT=101
#
# Verify that a room with id ROOM_ID does exist by sending a simlpe HTTP GET. If
# not abort since we are not allowed to initiate a room..
#
echo ">>> verifying that room '${ROOM_ID}' exists..."
${HTTPIE_COMMAND} \
GET ${SERVER_URL}/rooms/${ROOM_ID} > /dev/null
#
# Create a Broadcaster entity in the server by sending a POST with our metadata.
# Note that this is not related to mediasoup at all, but will become just a JS
# object in the Node.js application to hold our metadata and mediasoup Transports
# and Producers.
#
echo ">>> creating Broadcaster..."
${HTTPIE_COMMAND} \
POST ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters \
id="${BROADCASTER_ID}" \
displayName="Broadcaster" \
device:='{"name": "FFmpeg"}' \
> /dev/null
#
# Upon script termination delete the Broadcaster in the server by sending a
# HTTP DELETE.
#
trap 'echo ">>> script exited with status code $?"; ${HTTPIE_COMMAND} DELETE ${SERVER_URL}/rooms/${ROOM_ID}/broadcasters/${BROADCASTER_ID} > /dev/null' EXIT
#
# Create a PlainTransport in the mediasoup to send our audio using plain RTP
# over UDP. Do it via HTTP post specifying type:"plain" and comedia:true and
# rtcpMux:false.
#
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)
#
# Parse JSON response into Shell variables and extract the PlainTransport id,
# IP, port and RTCP port.
#
eval "$(echo ${res} | jq -r '@sh "audioTransportId=\(.id) audioTransportIp=\(.ip) audioTransportPort=\(.port) audioTransportRtcpPort=\(.rtcpPort)"')"
#
# Create a PlainTransport in the mediasoup to send our video using plain RTP
# over UDP. Do it via HTTP post specifying type:"plain" and comedia:true and
# rtcpMux:false.
#
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)
#
# Parse JSON response into Shell variables and extract the PlainTransport id,
# IP, port and RTCP port.
#
eval "$(echo ${res} | jq -r '@sh "videoTransportId=\(.id) videoTransportIp=\(.ip) videoTransportPort=\(.port) videoTransportRtcpPort=\(.rtcpPort)"')"
#
# Create a mediasoup Producer to send audio by sending our RTP parameters via a
# HTTP POST.
#
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
#
# Create a mediasoup Producer to send video by sending our RTP parameters via a
# HTTP POST.
#
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/vp8\", \"payloadType\":${VIDEO_PT}, \"clockRate\":90000 }], \"encodings\": [{ \"ssrc\":${VIDEO_SSRC} }] }" \
> /dev/null
#
# Run ffmpeg command and make it send audio and video RTP with codec payload and
# SSRC values matching those that we have previously signaled in the Producers
# creation above. Also, tell ffmpeg to send the RTP to the mediasoup
# PlainTransports' ip and port.
#
echo ">>> running ffmpeg..."
#
# NOTES:
# - We can add ?pkt_size=1200 to each rtp:// URI to limit the max packet size
# to 1200 bytes.
#
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}"