A Beginner's Guide to Building a Simple Live Streaming System with LiveGo, OBS, and flv.js
This guide walks beginners through setting up a basic live‑streaming pipeline using the open‑source LiveGo server, OBS for RTMP publishing, and flv.js for browser playback, while explaining push‑pull architecture, protocol choices, Docker deployment, and a Redis‑based chat system for live rooms.
With the arrival of 5G, the audio‑video industry is entering a new boom. Live streaming has become a core product form, ranging from show‑room streams to game streams, online education, e‑commerce, and many other emerging formats.
This article provides a concise tutorial on how to quickly set up a simple live streaming system and introduces the main architecture of mainstream streaming solutions.
1. Push‑pull streaming model
The overall push‑pull model consists of three main modules: the push (encoding) module, the RTMP server module, and the playback module. The push module captures audio‑video, optionally applies beauty filters, encodes the stream and sends it via RTMP to the server. The RTMP server (e.g., livego) receives the stream, performs transcoding, recording, and provides various playback protocols. The playback module retrieves the stream URL and renders it on the client side.
2. Building steps
2.1 Set up a live streaming server – The article recommends using the open‑source livego server, which is written in Go, cross‑platform, and supports RTMP, HLS, HTTP‑FLV, etc. Installation can be done via binary download, Docker, or source compilation. Example Docker command:
docker run -p 1935:1935 -p 7001:7001 -p 7002:7002 -p 8090:8090 -d gwuhaolin/livegoAfter the container starts, the server provides a default RTMP push URL rtmp://localhost:1935/live . The channel key required for authentication can be obtained via http://localhost:8090/control/get?room=movie , which returns a JSON response such as:
{
"status": 200,
"data": "rfBd56ti2SMtYvSgD5xAV0YU99zampta7Z7S575KLkIZ9PYk"
}2.2 Use OBS for pushing streams – OBS (Open Broadcaster Software) is a free, open‑source tool for video capture and encoding. Users create a new “Media Source” pointing to a local MP4 file (or any capture device), configure the stream URL and channel key obtained above, and start pushing the stream to the livego server.
2.3 Viewing the stream
Various playback methods are demonstrated:
VLC: open network stream rtmp://localhost:1935/live/movie for quick testing.
flv.js: a popular HTML5 JavaScript library for playing FLV streams in browsers. The demo page http://bilibili.github.io/flv.js/demo/ can be used by entering the HTTP‑FLV URL http://127.0.0.1:7001/live/movie.flv .
3. Streaming protocols overview
The article briefly compares RTMP, HLS, and HTTP‑FLV, describing their characteristics, platform support, latency, and typical use cases.
4. Live‑room message system
A simple message system is built using Redis Sorted Sets. Messages are stored with the room ID as the key, the message timestamp as the score, and the serialized JSON payload as the value. Sample Java code for inserting a message:
long time = new Date().getTime();
try {
// redis中插入消息数据
jedisTemplate.zadd(V_UNIQUE_ROOM_ID, time, JSON.toJSONString(roomMessage));
// 按照概率性的去删除redis中过期的消息数据
if (probability()) {
deleteOverTimeCache(V_UNIQUE_ROOM_ID);
}
} catch (Exception e) {
log.error("message save error", e);
}Code for deleting expired messages when the set size exceeds a threshold:
private void deleteOverTimeCache(String roomId) {
Long totalCount = jedisTemplate.zcard(roomId);
log.info("deleteOldTimeCache size is {}", totalCount);
if (totalCount < 600) {
return;
}
Set
tuples = jedisTemplate.zrangeWithScores(roomId, -601, -1);
if (CollectionUtils.isNotEmpty(tuples)) {
for (Tuple tuple : tuples) {
double score = tuple.getScore();
jedisTemplate.zremrangeByScore(roomId, 0d, score);
break;
}
}
}And the query interface used by the client to poll new messages:
@Override
public RoomMessage queryRoomMessages(MessageMessageReq messageMessageReq) {
RoomMessage result = new RoomMessage();
long timestamp = messageMessageReq.getTimestamp();
Set
tuples;
if (timestamp == 0) {
// first poll, return the latest message
tuples = jedisTemplate.zrevrangeWithScores(UNIQUE_ROOM_ID, 0, 0);
} else {
// subsequent polls, return up to 5 messages after the last timestamp
tuples = jedisTemplate.zrangeByScoreWithScores(UNIQUE_ROOM_ID, timestamp + 1, System.currentTimeMillis(), 0, 5);
}
List
eachRoomMessages = new ArrayList<>();
long lastTimestamp = 0L;
if (!CollectionUtils.isEmpty(tuples)) {
for (Tuple tuple : tuples) {
lastTimestamp = new Double(tuple.getScore()).longValue();
eachRoomMessages.add(JSON.parseObject(tuple.getElement(), EachRoomMessage.class));
}
}
result.setTimestamp(lastTimestamp);
result.setEachRoomMessages(eachRoomMessages);
return result;
}The article concludes that the presented material gives readers a foundational understanding of live streaming concepts, architecture, and practical implementation, laying the groundwork for deeper exploration.
vivo Internet Technology
Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.