Build a Real-Time Video Bullet Chat with Netty and WebSocket
This article walks through creating a real‑time video bullet‑chat system using Netty as the backend server and WebSocket for bidirectional communication, covering technology selection, architecture design, data flow, and detailed Java and HTML/JavaScript code to implement the interactive feature.
In 2021, with the rise of bullet‑screen interactions across video platforms, the author implemented a real‑time video bullet‑chat feature to enhance the experience of video playback, live streaming, PPT presentations, and lotteries.
1 Technology Selection
1.1 Netty
Netty is an asynchronous event‑driven network framework that supports many protocols such as FTP, SMTP, HTTP, and offers excellent performance, stability, and flexibility.
Netty’s architecture consists of three parts:
Core layer with zero‑copy, consistent interfaces, and extensible event model.
Transport media such as Socket, Datagram, Pipe, and HTTP Tunnel.
Supported protocols including HTTP/WebSocket, SSL, large files, compression, text, binary, and Google Protobuf.
1.2 WebSocket
WebSocket is a full‑duplex communication protocol over a single TCP connection, standardized as RFC 6455 in 2011 and supported by both IETF and W3C.
It simplifies data exchange between client and server, allowing the server to push data actively. After a single handshake, a persistent bidirectional channel is established.
1.3 Why Choose This Stack
Real‑time interaction requires bidirectional data transmission, which WebSocket provides.
Netty already supports the WebSocket protocol, making implementation straightforward.
2 Implementation Idea
2.1 Service Architecture
All clients maintain a bidirectional channel with the server.
2.2 Transmission Process
3 Result
3.1 Video Display
Below is the effect of the bullet‑chat overlay on a video.
4 Code Implementation
4.1 Project Structure
A Maven project containing all source files under a single package.
4.2 Java Server
The server consists of three classes: BulletChatServer, BulletChatInitializer, and BulletChatHandler.
4.2.1 Netty NIO Server
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public enum BulletChatServer {
SERVER;
private BulletChatServer() {
EventLoopGroup mainGroup = new NioEventLoopGroup();
EventLoopGroup subGroup = new NioEventLoopGroup();
ServerBootstrap server = new ServerBootstrap();
server.group(mainGroup, subGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new BulletChatInitializer());
ChannelFuture future = server.bind(9123);
}
public static void main(String[] args) {
// start server
}
}4.2.2 Initializer
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
public class BulletChatInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(1024 * 64));
pipeline.addLast(new IdleStateHandler(8, 10, 12));
pipeline.addLast(new WebSocketServerProtocolHandler("/lbh"));
pipeline.addLast(new BulletChatHandler());
}
}4.2.3 Handler
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
public class BulletChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
String content = msg.text();
System.err.println("Received: " + content);
channels.writeAndFlush(new TextWebSocketFrame(content));
System.err.println("Sent: " + content);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
channels.add(ctx.channel());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
String channelId = ctx.channel().id().asShortText();
System.out.println("Client removed, channelId: " + channelId);
channels.remove(ctx.channel());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.channel().close();
channels.remove(ctx.channel());
}
}4.3 Web Client
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Netty Video Bullet Chat</title>
<style>
/* basic styles omitted for brevity */
</style>
</head>
<body>
<div class="wrap flex-column">
<div class="box">
<video src="shape.mp4" width="100%" height="100%" controls autoplay></video>
</div>
<div class="send flex-row">
<input type="text" class="con" placeholder="Enter bullet chat..."/>
<div class="send-btn" onclick="sendMsg(document.querySelector('.con').value)">Send</div>
</div>
</div>
<script>
var ws = new WebSocket("ws://localhost:9123/lbh");
ws.onopen = function(){ alert("Connecting..."); };
ws.onmessage = function(e){ console.log("Received: " + e.data); createEle(e.data); };
ws.onclose = function(){ alert("Connection closed"); };
function sendMsg(msg){ ws.send(msg); }
// functions createEle, roll, random, etc. omitted for brevity
</script>
</body>
</html>The real‑time video bullet‑chat feature is now complete and can be tested easily.
5 Summary
The author finished the implementation quickly thanks to prior experience with Netty and related protocols. The tutorial provides a straightforward way to add interactive bullet‑chat to video streams, and readers are encouraged to try it and ask questions.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
