A real-time video streaming application built with Node.js, React.js, Express, and Socket.IO that recreates video playback by transmitting base64-encoded image frames over WebSockets. The server reads preprocessed frames, streams them to connected clients at a configurable frame rate, and manages real-time delivery, while the React frontend renders each frame dynamically in the browser.
Built in December 2018, it demonstrates WebSocket communication, event-driven architecture, frame synchronization, automatic reconnection, and custom media streaming without traditional video formats.
- 🎥 Real-time frame streaming via WebSocket (Socket.IO)
- 📡 Server-side frame management and distribution
- ⚛️ React.js client with dynamic image rendering
- 🔄 Automatic reconnection handling
- ⏱️ Configurable frame rate (~30 fps default)
- 🖼️ Base64 image encoding for frame transmission
- 📦 Separate client and server architecture
- Real-time streaming: Base64 frame delivery over Socket.IO
- Frame synchronization: Configurable playback rate (30fps default)
- Client-server architecture: Separate React frontend and Node.js backend
- Automatic reconnection: Handles client disconnections gracefully
- Dynamic rendering: React updates images as frames arrive
- Event-driven design: Socket.IO for real-time bidirectional communication
- Modular architecture: Clear separation between client and server
- Configuration management: Environment-specific settings for client
- Dependency management: npm for package management
- Modern frontend: React with component-based architecture
- Development servers: Hot reloading for both client and server
- Environment configurations: Development and production settings
- Clear project structure: Organized directories for easy navigation
- Well-documented code: Comments and structure for maintainability
graph LR
A[Video File] -->|Extract Frames| B[JPEG Images]
B -->|Convert to Base64| C[video.txt]
C -->|Read Frames| D[Node.js Server]
D -->|Socket.IO| E[React Client]
E -->|Render| F[Browser Display]
style A fill:#e1f5ff
style C fill:#fff4e1
style D fill:#ffe1f5
style E fill:#e1ffe1
style F fill:#f5e1ff
This project follows clean architecture principles:
- Separation of Concerns: Clear separation between client (presentation layer) and server (backend logic)
- Event-driven Communication: Socket.IO for real-time bidirectional communication
- Modular Design: Reusable React components and server-side modules
- Configuration Management: Environment-specific settings
- Testability: Clear code structure for easy testing and maintenance
- Observer Pattern: Socket.IO for real-time event handling
- Component Pattern: React for modular UI development
- Module Pattern: Node.js modules for server organization
- Factory Pattern: Component creation and initialization
sequenceDiagram
participant V as Video Source
participant S as Server
participant C as Client
participant B as Browser
V->>S: Load base64 frames from video.txt
C->>S: Connect via Socket.IO
S->>C: Connection established
loop Every 33ms
S->>C: Emit frame {image: true, buffer: base64}
C->>C: Convert base64 to image source
C->>B: Update <img> src
B->>B: Render frame
end
graph TD
A[App] --> B[Layout HOC]
B --> C[Home Container]
C --> D[Loader Component]
C --> E[Image Display]
C --> F[Socket.IO Client]
G[Server] --> H[Express]
G --> I[Socket.IO Server]
G --> J[File Reader]
F -.WebSocket.-> I
style C fill:#e1f5ff
style F fill:#ffe1e1
style G fill:#ffe1f5
style I fill:#ffe1e1
- Node.js (v8 or higher)
- npm (comes with Node.js)
- Modern web browser
- Clone the repository:
git clone https://github.com/orassayag/stream-images.git
cd stream-images- Install server dependencies:
cd server
npm install- Install client dependencies:
cd ../client
npm install- Start the server (in the server directory):
npm startThe server will run on http://localhost:3000
- Start the client (in a new terminal, in the client directory):
npm startThe client will automatically open in your browser at http://localhost:3001
Server (server/index.js):
- Frame rate: Adjust the interval value (default: 33ms = ~30fps)
- Port: Change the port number in
http.listen()
Client (client/src/settings/):
- API endpoint: Update
api_base_urlin settings files
Linting:
# Server
cd server
npm run lint
# Client
cd client
npm run lintBuilding for Production:
# Client
cd client
npm run build- Start both server and client
- Open browser developer console
- Verify Socket.IO connection is established
- Check for any console errors
- Observe frame streaming in the network tab
stream-images/
├── client/ # React.js frontend
│ ├── public/ # Static assets
│ ├── src/
│ │ ├── components/ # Reusable React components
│ │ │ └── UI/
│ │ │ └── Loader/
│ │ ├── containers/ # Container components (Home)
│ │ ├── hoc/ # Higher-order components (Layout)
│ │ ├── settings/ # Environment configurations
│ │ └── utils/ # Utility functions
│ ├── config/ # Webpack and Jest configs
│ ├── scripts/ # Build and dev scripts
│ └── package.json
├── server/ # Node.js backend
│ ├── index.js # Main server file
│ ├── video.txt # Base64 encoded frames (not in repo)
│ ├── images/ # Source images for conversion
│ └── package.json
├── .github/ # GitHub configuration
├── .vscode/ # VS Code settings
├── .gitignore
├── .prettierrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── INSTRUCTIONS.md
├── LICENSE
├── README.md
└── SECURITY.md
- Extract frames from a video file using FFmpeg:
ffmpeg -i input_video.mp4 -vf fps=30 images/frame_%04d.jpg- Convert frames to base64 and store in
video.txt(see server code comments)
- Reads pre-converted base64 frames from
video.txt - Splits frames using
#delimiter - Establishes Socket.IO connection with clients
- Emits frames sequentially at configured intervals
- Connects to server via Socket.IO
- Listens for
imageevents - Converts base64 data to image source
- Updates the DOM with the new frame
- React.js - Frontend framework
- Node.js - Backend runtime
- Socket.IO - Real-time bidirectional event-based communication
- Express - Web framework for Node.js
- LESS - CSS preprocessor
- Webpack - Module bundler
npm start- Start development servernpm run build- Build for productionnpm test- Run tests
npm start- Start the server
- Understand the Architecture: Review the architecture diagrams and documentation
- Test Changes Locally: Always test changes before committing
- Follow Code Style: Use existing ESLint and Prettier configurations
- Update Documentation: Update README and INSTRUCTIONS.md when adding features
- Environment Management: Use development environment for testing
- Code Quality: Run linting before committing
- Version Control: Follow SemVer for versioning
- Security: Never commit sensitive data
- Performance: Optimize frame size and quality for better streaming
- Monitoring: Check console logs for errors
- Maintenance: Keep dependencies updated
Contributions are welcome! Please read CONTRIBUTING.md for details on the code of conduct and the process for submitting pull requests.
We use SemVer for versioning. For the versions available, see the tags on this repository.
For questions, issues, or contributions:
- GitHub Issues: https://github.com/orassayag/stream-images/issues
- Email: orassayag@gmail.com
- Or Assayag - Initial work - orassayag
- Or Assayag orassayag@gmail.com
- GitHub: https://github.com/orassayag
- StackOverflow: https://stackoverflow.com/users/4442606/or-assayag?tab=profile
- LinkedIn: https://linkedin.com/in/orassayag
This application has an MIT license - see the LICENSE file for details.
- Built for educational and research purposes
- Respects robots.txt and implements rate limiting
- Uses user-agent rotation to avoid detection
- Implements polite crawling practices