Skip to content

Commit

Permalink
Switch Flask to Fastapi in streaming web
Browse files Browse the repository at this point in the history
  • Loading branch information
yihong1120 committed Nov 7, 2024
1 parent aa42022 commit 9752df4
Show file tree
Hide file tree
Showing 10 changed files with 600 additions and 508 deletions.
126 changes: 41 additions & 85 deletions examples/streaming_web/READMD-zh-tw.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,115 +3,71 @@

# 即時串流網頁範例

此部分提供一個即時串流網頁應用程式的實作範例,設計目的是為了實現即時的攝影機串流畫面更新。本指南提供如何使用、配置及瞭解此應用程式的特點與功能
本節提供了一個 Streaming Web 應用程序的範例實作,旨在促進即時相機畫面傳輸和更新。此指南提供有關如何使用、配置和了解該應用程序功能的信息

## 使用方法
## 使用方式

1. **啟動伺服器:**
```sh
python app.py
```

或者使用 Gunicorn 啟動應用程式,並設定非同步工作執行緒:
或是

```sh
gunicorn -w 1 -k eventlet -b 127.0.0.1:8000 "examples.streaming_web.app:app"
uvicorn examples.streaming_web.app:sio_app --host 127.0.0.1 --port 8000
```

2. **訪問應用程式:**
打開網頁瀏覽器,並導向以下網址:
2. **打開您的網頁瀏覽器並導航至:**
```sh
http://localhost:8000
```

## 功能

- **即時串流**顯示即時的攝影機畫面,每 5 秒自動更新
- **WebSocket 整合**使用 WebSocket 進行高效的即時通訊
- **動態內容加載**自動更新攝影機圖片,無需重新整理頁面
- **響應式設計**適應不同螢幕尺寸,提供無縫的使用者體驗
- **可自定義的佈局**透過 CSS 調整佈局和樣式,以符合個人需求
- **即時流媒體**顯示即時相機畫面,每5秒自動更新一次
- **WebSocket 整合**利用 WebSocket 進行高效的即時通信
- **動態內容加載**無需刷新頁面即可自動更新相機圖像
- **響應式設計**適應各種屏幕尺寸,提供無縫的用戶體驗
- **可定制的佈局**使用 CSS 調整佈局和樣式。

## 配置和檔案概覽
## 配置

此應用程式可透過以下關鍵檔案進行自訂和配置
可以通過以下文件配置應用程序

- **app.py**啟動伺服器並定義路由的主要應用程式檔案
- **routes.py**定義網頁路由及其相應的處理器
- **app.py**啟動伺服器並定義路由的主要應用文件
- **routes.py**定義網頁路由及其相應的處理程序
- **sockets.py**:管理 WebSocket 連接和事件。
- **utils.py**:包含應用程式使用的實用工具函式。
- **index.js**:處理主頁面中攝影機圖片的動態更新。
- **camera.js**:管理攝影機畫面的更新。
- **label.js**:處理 WebSocket 通訊和基於標籤的更新。
- **styles.css**:包含網頁應用程式的樣式,確保響應式和可存取的設計。

請務必根據環境需求檢查並調整這些檔案中的配置設定。

## Nginx 配置範例

若要使用 Nginx 作為此 FastAPI 應用程式的反向代理,可以參考以下關鍵配置部分。完整的範例配置檔案請參見 `config/` 目錄中的 `nginx_config_example.conf`

1. **HTTP 重定向至 HTTPS**:將所有 HTTP 請求重定向到 HTTPS,確保安全通訊。
```nginx
server {
listen 80;
server_name yourdomain.com;
location / {
return 301 https://$server_name$request_uri;
}
}
```
- **utils.py**:應用程序中使用的實用函數。
- **index.js**:處理主頁面動態圖像更新。
- **camera.js**:管理相機圖像更新。
- **label.js**:處理基於標籤的 WebSocket 通信和更新。
- **styles.css**:包含網頁應用程序的樣式,確保響應式和無障礙設計。

2. **HTTPS 配置**:啟用 SSL 憑證並代理靜態文件和 WebSocket 請求。
```nginx
server {
listen 443 ssl;
server_name yourdomain.com;
# SSL 憑證路徑
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# 靜態文件
location /upload/ {
alias /home/youruser/Documents/Construction-Hazard-Detection/static/uploads/;
autoindex on;
allow all;
}
# WebSocket 配置
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
# 傳遞額外的客戶端資訊標頭
}
# 一般 HTTP 代理
location / {
proxy_pass http://127.0.0.1:8000;
# 傳遞客戶端及 SSL 狀態的標頭
}
}
```
## 文件概述

### app.py
啟動伺服器並設置路由的應用程序主入口。

### routes.py
定義各種網頁路由及其相應的請求處理程序。

### sockets.py
管理 WebSocket 連接,處理連接、重新連接和更新事件。

3. **SSL 憑證設定**
### utils.py
包含應用程序中使用的實用函數。

若要使用 SSL 保護伺服器,可以使用 Let's Encrypt 提供的免費 SSL 憑證。建議步驟如下:
### index.js
使用 jQuery 定期更新主頁面的相機圖像。

- **安裝 Certbot**:使用 Certbot 來自動處理 SSL 憑證的安裝和續期。
- **取得 SSL 憑證**:使用您的網域名稱運行 Certbot 以創建 SSL 憑證:
```sh
sudo certbot --nginx -d yourdomain.com
```
- **設置自動續期**:Certbot 會自動處理憑證的續期,您可以新增 Cron 排程定期檢查:
```sh
0 12 * * * /usr/bin/certbot renew --quiet
```
### camera.js
通過刷新圖像源每5秒更新頁面上的相機圖像。

此配置確保 Nginx 伺服器的安全性,並自動管理 SSL 憑證。
### label.js
管理 WebSocket 連接,處理當前頁面標籤顯示的更新。

## 其他注意事項
### styles.css
定義應用程序的樣式,包括響應式設計、強制顏色調整以確保無障礙性以及平滑的圖像過渡效果。

欲進一步自訂應用程式,請參考 `examples/streaming_web` 資料夾並根據專案需求調整檔案。此程式碼具有模組化設計,允許您更新或替換組件,以適應擴展性和維護性需求
請確保檢查並調整相應文件中的配置設置以適應您的具體需求
108 changes: 32 additions & 76 deletions examples/streaming_web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,106 +12,62 @@ This section provides an example implementation of a Streaming Web application,
python app.py
```

Alternatively, use Gunicorn to start the application with an asynchronous worker:
or

```sh
gunicorn -w 1 -k eventlet -b 127.0.0.1:8000 "examples.streaming_web.app:app"
uvicorn examples.streaming_web.app:sio_app --host 127.0.0.1 --port 8000
```

2. **Access the application:**
Open your web browser and navigate to:
2. **Open your web browser and navigate to:**
```sh
http://localhost:8000
```

## Features

- **Real-Time Streaming**: Displays real-time camera feeds with automatic updates every 5 seconds.
- **Real-Time Streaming**: Display real-time camera feeds with automatic updates every 5 seconds.
- **WebSocket Integration**: Utilises WebSocket for efficient real-time communication.
- **Dynamic Content Loading**: Automatically updates camera images without page refresh.
- **Dynamic Content Loading**: Automatically updates camera images without refreshing the page.
- **Responsive Design**: Adapts to various screen sizes for a seamless user experience.
- **Customisable Layout**: Modify layout and styles using CSS for a tailored appearance.
- **Customisable Layout**: Adjust layout and styles using CSS.

## Configuration and File Overview
## Configuration

The application can be customised and configured via the following key files:
The application can be configured through the following files:

- **app.py**: Main application file that starts the server and defines the routes.
- **routes.py**: Defines web routes and their respective handlers.
- **routes.py**: Defines the web routes and their respective handlers.
- **sockets.py**: Manages WebSocket connections and events.
- **utils.py**: Contains utility functions for the application.
- **index.js**: Handles dynamic image updates on the main page.
- **utils.py**: Utility functions for the application.
- **index.js**: Handles dynamic image updates for the main page.
- **camera.js**: Manages the camera image updates.
- **label.js**: Handles WebSocket communication and label-based updates.
- **styles.css**: Contains the styles for the web application, ensuring responsive and accessible design.

Ensure to review and adjust configuration settings in these files as necessary for your environment.
- **label.js**: Handles WebSocket communication and updates based on labels.
- **styles.css**: Contains the styles for the web application, ensuring a responsive and accessible design.

## Nginx Configuration Example
## File Overview

To use Nginx as a reverse proxy for this FastAPI application, you may refer to the following key configuration parts. For a complete example configuration file, see `nginx_config_example.conf` in the `config/` directory.
### app.py
The main entry point of the application that starts the server and sets up routes.

1. **HTTP Redirect to HTTPS**: Redirect all HTTP requests to HTTPS for secure communication.
```nginx
server {
listen 80;
server_name yourdomain.com;
location / {
return 301 https://$server_name$request_uri;
}
}
```
### routes.py
Defines the various web routes and their respective request handlers.

2. **HTTPS Configuration**: Enables SSL certificates and proxies static files and WebSocket requests.
```nginx
server {
listen 443 ssl;
server_name yourdomain.com;
# SSL certificate paths
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Static files
location /upload/ {
alias /home/youruser/Documents/Construction-Hazard-Detection/static/uploads/;
autoindex on;
allow all;
}
# WebSocket configuration
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
# Additional headers to forward client information
}
# General HTTP proxy
location / {
proxy_pass http://127.0.0.1:8000;
# Forward headers for client and SSL status
}
}
```
### sockets.py
Manages WebSocket connections, handling events such as connection, reconnection, and updates.

3. **SSL Certificate Setup**
### utils.py
Contains utility functions used across the application for various tasks.

To secure the server with SSL, a free SSL certificate from Let's Encrypt can be used. Here are the recommended steps:
### index.js
Handles the periodic update of camera images on the main page using jQuery.

- **Install Certbot**: Use Certbot to handle automatic SSL certificate installation and renewal.
- **Obtain SSL Certificates**: Run Certbot with your domain name to create SSL certificates:
```sh
sudo certbot --nginx -d yourdomain.com
```
- **Set Up Automatic Renewal**: Certbot handles automatic renewal; however, you can add a Cron job to check periodically:
```sh
0 12 * * * /usr/bin/certbot renew --quiet
```
### camera.js
Updates the camera images on the page by refreshing the image source every 5 seconds.

This setup ensures secure, automatic SSL management for the Nginx server.
### label.js
Manages WebSocket connections, handling updates based on the current label displayed on the page.

## Additional Notes
### styles.css
Defines the styling for the application, including responsive design, forced color adjustments for accessibility, and smooth image transitions.

For further customisation, refer to the `examples/streaming_web` folder and adjust files as per project needs. The code is modular, allowing you to update or replace components for scalability and maintenance.
Ensure to review and adjust the configuration settings in the respective files to suit your specific requirements.
85 changes: 58 additions & 27 deletions examples/streaming_web/app.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,73 @@
from __future__ import annotations

import os
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager

import redis
from dotenv import load_dotenv
from flask import Flask
from flask_cors import CORS
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_socketio import SocketIO
import socketio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi_limiter import FastAPILimiter

from .routes import register_routes
from .sockets import register_sockets
from .utils import redis_manager

load_dotenv()

# Redis configuration
redis_host: str = os.getenv('redis_host') or 'localhost'
redis_port: int = int(os.getenv('redis_port') or 6379)
redis_password: str | None = os.getenv('redis_password') or None
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None]:
"""
Initialises resources at startup and performs cleanup on shutdown.
# Connect to Redis
r = redis.StrictRedis(
host=redis_host,
port=redis_port,
password=redis_password,
decode_responses=False,
Args:
app (FastAPI): The FastAPI application instance.
Yields:
None
"""
# Initialises rate limiter with the Redis client
await FastAPILimiter.init(redis_manager.client)
try:
yield
finally:
# Cleanup code: Closes the Redis connection after application shutdown
await redis_manager.client.close()
print('Redis connection closed.')


# Create the FastAPI application with a lifespan manager for setup and cleanup
app = FastAPI(lifespan=lifespan)

# Add CORS middleware to allow cross-origin requests
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)

app = Flask(__name__)
CORS(app) # Allow cross-origin requests from any domain
# Allow all origins for WebSocket connections
socketio = SocketIO(app, cors_allowed_origins='*')
limiter = Limiter(key_func=get_remote_address)
# Mount the static files directory to serve static assets
app.mount(
'/static',
StaticFiles(directory='examples/streaming_web/static'),
name='static',
)

# Initialise Socket.IO server with ASGI support
sio = socketio.AsyncServer(async_mode='asgi')
sio_app = socketio.ASGIApp(sio, app)

register_routes(app, limiter, r)
register_sockets(socketio, r)
# Register application routes and Socket.IO events
register_routes(app)
register_sockets(sio, redis_manager)

# Run the application using Uvicorn ASGI server
if __name__ == '__main__':
socketio.run(app, host='127.0.0.1', port=8000, debug=False)
import uvicorn
uvicorn.run(
'examples.streaming_web.app:sio_app',
host='127.0.0.1',
port=8000,
log_level='info',
)
Loading

0 comments on commit 9752df4

Please sign in to comment.