文章目录
- 建议还是clone完整项目去尝试运行一下,整体描述感觉有点乱。
- requirementx.txt amqp==2.6.1 celery-with-redis==3.0 celery==4.4.7 channels==3.0.5 daphne==3.0.2 django-celery-beat==2.3.0 django-celery==3.3.1 django-cors-headers==3.13.0 django-crispy-forms==1.14.0 django-filter==21.1 django-formtools==2.3 django-import-export==2.6.0 django-redis-sessions==0.6.2 django-reversion==5.0.0 django-simpleui==2022.4.9 django-timezone-field==5.0 django-tinymce==3.4.0 django-utils-six==2.0 Django==3.2 redis==4.3.1 six==1.15.0 install pip install -r requirements.txt 目录结构如图所示
- asgi.py配置,用于区分http和websocket的通信路由 """ ASGI config for videotest project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ """ import os from channels.routing import ProtocolTypeRouter, URLRouter from django.core.asgi import get_asgi_application from channels.auth import AuthMiddlewareStack from . import routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'videotest.settings') # application = get_asgi_application() application = ProtocolTypeRouter({ "http": get_asgi_application(), "websocket": AuthMiddlewareStack( URLRouter( routing.websocket_urlpatterns ) ), }) settings.py配置,后期websocket通信要用,注意这里用到了redis中间件。 # WebSocket ASGI_APPLICATION = 'videotest.asgi.application' CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('127.0.0.1', 6379)], 'capacity': 6000, 'expiry': 30, }, }, }
- 在project目录下新建立routing.py文件,内容如下: from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('video/', include('video.urls')), ] 配置项目urls.py # videotest/routing.py from django.urls import re_path import video.consumers websocket_urlpatterns = [ re_path(r'ws/video/(?P<v_name>\w+)/$', video.consumers.VideoConsumer.as_asgi()) ] 配置app的urls.py文件 # video/urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('<str:v_name>/', views.v_name, name='v_name'), ]
- 配置websocket的consumers.py文件,内容如下 # video/consumers.py import json from channels.generic.websocket import AsyncWebsocketConsumer class VideoConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['v_name'] self.room_group_name = 'video_%s' % self.room_name print(self.room_name) # Join room group await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): # Leave room group await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) # Receive message from WebSocket async def receive(self, text_data): print("receive:", text_data) # print(1) # Send message to room group await self.channel_layer.group_send( self.room_group_name, { 'type': 'video_message', 'message': text_data, } ) # Receive message from room group async def video_message(self, event): # print(1) message = event['message'] # Send message to WebSocket await self.send(text_data=json.dumps({ 'message': message })) 视图views.py from django.shortcuts import render # Create your views here. # video/views.py # Create your views here. def index(request): return render(request, 'video/index.html') def v_name(request, v_name): return render(request, 'video/video.html', { 'v_name': v_name })
- settings.py中模板路径设置 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # 主要是这里 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] video.html <!--video.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Video</title> </head> <body> <div align="center"> <h1>Video</h1> <img id="resImg" src="" /> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js" ></script> <script> const ws = new WebSocket( 'ws://' + window.location.host + '/ws/video/' + 'wms' + '/' ); ws.onmessage = function(evt) { v_data = JSON.parse(evt.data); $("#resImg").attr("src", v_data.message); //console.log( "Received Message: " + v_data.message); // ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); }; </script> </body> </html>
-
- 这个是必需的,nginx用来接受websocket请求并进行相关的配置。 config user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; upstream django { server 0.0.0.0:8000; } upstream wsbackend { server 0.0.0.0:8001; } server { listen 81; # 这里server_name改成服务器的公网IP server_name 127.0.0.1; charset UTF-8; # 两个日志文件路径随意 access_log /var/log/nginx/mysite_access.log; error_log /var/log/nginx/mysite_error.log; client_max_body_size 75M; client_body_buffer_size 256k; proxy_connect_timeout 180; proxy_send_timeout 180; proxy_read_timeout 180; proxy_buffer_size 128k; proxy_buffers 32 64k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; # 通常请求交给uwsgi location / { include uwsgi_params; uwsgi_pass django; # uwsgi_read_timeout 2; } # websocket请求交给daphne location /ws { proxy_pass http://wsbackend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } } access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } 重载/重启 service nginx reload service nginx restart
- 启动awsgi 一般装channels会安装,如无则用pip装一下。 daphne -b 0.0.0.0 -p 8001 videotest.asgi:application
- 测试代码 # send_video.py import asyncio import websockets import numpy as np import cv2 import base64 import time capture = cv2.VideoCapture(0) if not capture.isOpened(): print('quit') quit() ret, frame = capture.read() encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 1] # 向服务器端实时发送视频截图 async def send_video(websocket): global ret, frame # global cam while True: time.sleep(0.1) result, imgencode = cv2.imencode('.jpg', frame, encode_param) data = np.array(imgencode) img = data.tobytes() # base64编码传输 img = base64.b64encode(img).decode() await websocket.send("data:image/jpg;base64," + img) ret, frame = capture.read() async def main_logic(): async with websockets.connect('ws://127.0.0.1:81/ws/video/wms/') as websocket: await send_video(websocket) asyncio.get_event_loop().run_until_complete(main_logic()) 测试 python send_video.py
- Django channels摄像头实时视频传输 Django-Channels使用和部署 Django-Channels使用和部署

最近在尝试搞搞Django的视频传输,最后找到了一个例子(上图是质量调整),怎么说呢,除了运行一段时间就卡住了,其它感觉还好,目前未找到具体卡顿的原因。如需了解完整的代码,欢迎访问如下地址去查看。
建议还是clone完整项目去尝试运行一下,整体描述感觉有点乱。
建议还是clone完整项目去尝试运行一下,整体描述感觉有点乱。
requirementx.txt
amqp==2.6.1
celery-with-redis==3.0
celery==4.4.7
channels==3.0.5
daphne==3.0.2
django-celery-beat==2.3.0
django-celery==3.3.1
django-cors-headers==3.13.0
django-crispy-forms==1.14.0
django-filter==21.1
django-formtools==2.3
django-import-export==2.6.0
django-redis-sessions==0.6.2
django-reversion==5.0.0
django-simpleui==2022.4.9
django-timezone-field==5.0
django-tinymce==3.4.0
django-utils-six==2.0
Django==3.2
redis==4.3.1
six==1.15.0
- install
pip install -r requirements.txt
- 目录结构如图所示
requirementx.txtamqp==2.6.1
celery-with-redis==3.0
celery==4.4.7
channels==3.0.5
daphne==3.0.2
django-celery-beat==2.3.0
django-celery==3.3.1
django-cors-headers==3.13.0
django-crispy-forms==1.14.0
django-filter==21.1
django-formtools==2.3
django-import-export==2.6.0
django-redis-sessions==0.6.2
django-reversion==5.0.0
django-simpleui==2022.4.9
django-timezone-field==5.0
django-tinymce==3.4.0
django-utils-six==2.0
Django==3.2
redis==4.3.1
six==1.15.0
pip install -r requirements.txt

asgi.py配置,用于区分http和websocket的通信路由
"""
ASGI config for videotest project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'videotest.settings')
# application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
),
})
settings.py配置,后期websocket通信要用,注意这里用到了redis中间件。
# WebSocket
ASGI_APPLICATION = 'videotest.asgi.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
'capacity': 6000,
'expiry': 30,
},
},
}
asgi.py配置,用于区分http和websocket的通信路由"""
ASGI config for videotest project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'videotest.settings')
# application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
),
})
settings.py配置,后期websocket通信要用,注意这里用到了redis中间件。# WebSocket
ASGI_APPLICATION = 'videotest.asgi.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
'capacity': 6000,
'expiry': 30,
},
},
}
- 在project目录下新建立
routing.py文件,内容如下:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('video/', include('video.urls')),
]
- 配置项目
urls.py
# videotest/routing.py
from django.urls import re_path
import video.consumers
websocket_urlpatterns = [
re_path(r'ws/video/(?P<v_name>\w+)/$', video.consumers.VideoConsumer.as_asgi())
]
- 配置app的
urls.py文件
# video/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:v_name>/', views.v_name, name='v_name'),
]
routing.py文件,内容如下:from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('video/', include('video.urls')),
]
urls.py# videotest/routing.py
from django.urls import re_path
import video.consumers
websocket_urlpatterns = [
re_path(r'ws/video/(?P<v_name>\w+)/$', video.consumers.VideoConsumer.as_asgi())
]
urls.py文件# video/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:v_name>/', views.v_name, name='v_name'),
]
- 配置websocket的
consumers.py文件,内容如下
# video/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class VideoConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['v_name']
self.room_group_name = 'video_%s' % self.room_name
print(self.room_name)
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
print("receive:", text_data)
# print(1)
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'video_message',
'message': text_data,
}
)
# Receive message from room group
async def video_message(self, event):
# print(1)
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
- 视图views.py
from django.shortcuts import render
# Create your views here.
# video/views.py
# Create your views here.
def index(request):
return render(request, 'video/index.html')
def v_name(request, v_name):
return render(request, 'video/video.html', {
'v_name': v_name
})
consumers.py文件,内容如下# video/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class VideoConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['v_name']
self.room_group_name = 'video_%s' % self.room_name
print(self.room_name)
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
print("receive:", text_data)
# print(1)
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'video_message',
'message': text_data,
}
)
# Receive message from room group
async def video_message(self, event):
# print(1)
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
from django.shortcuts import render
# Create your views here.
# video/views.py
# Create your views here.
def index(request):
return render(request, 'video/index.html')
def v_name(request, v_name):
return render(request, 'video/video.html', {
'v_name': v_name
})
settings.py中模板路径设置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 主要是这里
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- video.html
<!--video.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Video</title>
</head>
<body>
<div align="center">
<h1>Video</h1>
<img id="resImg" src="" />
</div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js" ></script>
<script>
const ws = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/video/'
+ 'wms'
+ '/'
);
ws.onmessage = function(evt) {
v_data = JSON.parse(evt.data);
$("#resImg").attr("src", v_data.message);
//console.log( "Received Message: " + v_data.message);
// ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
</script>
</body>
</html>
settings.py中模板路径设置TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 主要是这里
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
<!--video.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Video</title>
</head>
<body>
<div align="center">
<h1>Video</h1>
<img id="resImg" src="" />
</div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js" ></script>
<script>
const ws = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/video/'
+ 'wms'
+ '/'
);
ws.onmessage = function(evt) {
v_data = JSON.parse(evt.data);
$("#resImg").attr("src", v_data.message);
//console.log( "Received Message: " + v_data.message);
// ws.close();
};
ws.onclose = function(evt) {
console.log("Connection closed.");
};
</script>
</body>
</html>
这个是必需的,nginx用来接受websocket请求并进行相关的配置。
- config
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
upstream django {
server 0.0.0.0:8000;
}
upstream wsbackend {
server 0.0.0.0:8001;
}
server {
listen 81;
# 这里server_name改成服务器的公网IP
server_name 127.0.0.1;
charset UTF-8;
# 两个日志文件路径随意
access_log /var/log/nginx/mysite_access.log;
error_log /var/log/nginx/mysite_error.log;
client_max_body_size 75M;
client_body_buffer_size 256k;
proxy_connect_timeout 180;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_buffer_size 128k;
proxy_buffers 32 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
# 通常请求交给uwsgi
location / {
include uwsgi_params;
uwsgi_pass django;
# uwsgi_read_timeout 2;
}
# websocket请求交给daphne
location /ws {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
- 重载/重启
service nginx reload
service nginx restart
这个是必需的,nginx用来接受websocket请求并进行相关的配置。
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
upstream django {
server 0.0.0.0:8000;
}
upstream wsbackend {
server 0.0.0.0:8001;
}
server {
listen 81;
# 这里server_name改成服务器的公网IP
server_name 127.0.0.1;
charset UTF-8;
# 两个日志文件路径随意
access_log /var/log/nginx/mysite_access.log;
error_log /var/log/nginx/mysite_error.log;
client_max_body_size 75M;
client_body_buffer_size 256k;
proxy_connect_timeout 180;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_buffer_size 128k;
proxy_buffers 32 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
# 通常请求交给uwsgi
location / {
include uwsgi_params;
uwsgi_pass django;
# uwsgi_read_timeout 2;
}
# websocket请求交给daphne
location /ws {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
service nginx reload
service nginx restart
- 启动awsgi
一般装channels会安装,如无则用pip装一下。
daphne -b 0.0.0.0 -p 8001 videotest.asgi:application
一般装channels会安装,如无则用pip装一下。
daphne -b 0.0.0.0 -p 8001 videotest.asgi:application
- uwsgi 配置
# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# 使用nginx连接时使用
socket = 0.0.0.0:8000
# 不用nginx直接当web服务器使用
# http=0.0.0.0:9000
# 项目根目录的绝对路径
chdir = /mnt/d/PROJECT/videotest
# 相对项目根目录路径的项目中wsgi.py的相对路径
wsgi-file = videotest/wsgi.py
# process-related settings
# master
master = True
# maximum number of worker processes
processes = 8
threads = 4
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
# vacuum = true
pidfile = uwsgi.pid
daemonize = uwsgi.log
buffer-size=3276800
- 启动
uwsgi --ini uwsgi.ini
# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# 使用nginx连接时使用
socket = 0.0.0.0:8000
# 不用nginx直接当web服务器使用
# http=0.0.0.0:9000
# 项目根目录的绝对路径
chdir = /mnt/d/PROJECT/videotest
# 相对项目根目录路径的项目中wsgi.py的相对路径
wsgi-file = videotest/wsgi.py
# process-related settings
# master
master = True
# maximum number of worker processes
processes = 8
threads = 4
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
# vacuum = true
pidfile = uwsgi.pid
daemonize = uwsgi.log
buffer-size=3276800
uwsgi --ini uwsgi.ini
- 测试代码
# send_video.py
import asyncio
import websockets
import numpy as np
import cv2
import base64
import time
capture = cv2.VideoCapture(0)
if not capture.isOpened():
print('quit')
quit()
ret, frame = capture.read()
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 1]
# 向服务器端实时发送视频截图
async def send_video(websocket):
global ret, frame
# global cam
while True:
time.sleep(0.1)
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = np.array(imgencode)
img = data.tobytes()
# base64编码传输
img = base64.b64encode(img).decode()
await websocket.send("data:image/jpg;base64," + img)
ret, frame = capture.read()
async def main_logic():
async with websockets.connect('ws://127.0.0.1:81/ws/video/wms/') as websocket:
await send_video(websocket)
asyncio.get_event_loop().run_until_complete(main_logic())
- 测试
python send_video.py
# send_video.py
import asyncio
import websockets
import numpy as np
import cv2
import base64
import time
capture = cv2.VideoCapture(0)
if not capture.isOpened():
print('quit')
quit()
ret, frame = capture.read()
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 1]
# 向服务器端实时发送视频截图
async def send_video(websocket):
global ret, frame
# global cam
while True:
time.sleep(0.1)
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = np.array(imgencode)
img = data.tobytes()
# base64编码传输
img = base64.b64encode(img).decode()
await websocket.send("data:image/jpg;base64," + img)
ret, frame = capture.read()
async def main_logic():
async with websockets.connect('ws://127.0.0.1:81/ws/video/wms/') as websocket:
await send_video(websocket)
asyncio.get_event_loop().run_until_complete(main_logic())
python send_video.py
