11.nginx upload module + python django 后台 实现视频上传与切片

1.需求:支持视频上传并切片,支持通过m3u8文件播放

2.视频切片的上一节已经谈过,这一节主要是视频上传的处理

第一步:upload-module模块安装

-----------首先下载upload-module

-----------然后使用源码编译安装nginx: .configure --add-module=/path/nginx-upload-module/

第二步:确认是否已经安装了upload-module,使用指令:/usr/local/nginx/sbin/nginx -V

第三部:添加配置文件

http {
    include       mime.types;
    default_type  application/octet-stream;
    client_max_body_size 3000m;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 2 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;
    
    add_header Access-Control-Allow-Origin "http://weibo.duoyioa.com";
    add_header Access-Control-Allow-Headers X-Requested-With;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  300;
    
    #gzip  on;
    
     server {
     client_max_body_size 3000m;
     client_body_buffer_size 400m;
     listen 80;
     listen 443 ssl;

    ssl_certificate /usr/local/nginx/ssl/duoyioa.cer;
    ssl_certificate_key /usr/local/nginx/ssl/duoyioa.key;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;
     
     # Upload form should be submitted to this location
    location /upload {
        # Pass altered request body to this location
        upload_pass   @python;

        # Store files to this directory
        # The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
        upload_store /var 1;

        # Allow uploaded files to be read only by user
        upload_store_access user:rw;

        # Set specified fields in request body
        upload_set_form_field $upload_field_name.name "$upload_file_name";
        upload_set_form_field $upload_field_name.content_type "$upload_content_type";
        upload_set_form_field $upload_field_name.path "$upload_tmp_path";

        # Inform backend about hash and size of a file
        upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
        upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";

        upload_pass_form_field "^submit$|^description$";

        upload_cleanup 400 404 499 500-505;
        upload_limit_rate 0;
        upload_max_file_size    3000m;
        client_max_body_size    3000m;  
    }
    
    error_page   405 =200 @405;
    location @405 {
        return 200;
    }

    # Pass altered request body to a backend
    location @python {
        proxy_read_timeout 3000;
        proxy_connect_timeout 3000;
        proxy_pass   http://121.201.116.242:9999;
        #return 200;
    }
     
     location /hls { 
       types {
         application/vnd.apple.mpegurl m3u8;
         video/mp2t ts;
         video/mp4                            f4p f4v m4v mp4; 
         image/bmp                            bmp; 
         image/gif                            gif; 
         image/jpeg                            jpeg jpg; 
         image/png                            png; 
         image/svg+xml                        svg svgz; 
         image/tiff                            tif tiff; 
         image/vnd.wap.wbmp                    wbmp; 
         image/webp                            webp; 
         image/x-jng                          jng; 
       }
       root /var;
       add_header Cache-Control no-cache;
       add_header Access-Control-Allow-Origin *;
     }
  }
}

第四步:搭建python后台站点

主要的处理代码如下(有一些是业务处理代码,大体看upload就ok):

# -*- coding: utf-8 -*-
import os
import json
import uuid
import threading
import thread_manager
import datetime
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from logging_manager import single_logger
import logging
import traceback


UPLOAD_FILE_PATH = '/var/hls/video/'
ADDVIDEO_WEIBO_URL = "http://10.32.64.194:8233/api/Video/Insert"
UPDATE_WEIBO_JSONDATA = "http://10.32.64.194:8233/api/Video/UpdateJsonData"
VERIFY_VIDEO_TOKEN = 'http://10.32.64.194:8233/api/NoLogin/VerifyVideoToken'
THREAD_MANAGER = thread_manager.Thread_Pool(8)

@csrf_exempt
def upload(request):
    try:
        if verify_to_weibo(request.META['QUERY_STRING']) == False:#权限验证
            content = json.dumps({
                'message' : 'You have no authority',
                'code' : 96
            })
            response = HttpResponse(content, content_type='application/json; charset=utf-8')
            single_logger.info('非法的调用:%s' % request.META['QUERY_STRING'])
            return response
        
        request_params = request.POST
        file_name = request_params['file.name']
        file_content_type = request_params['file.content_type']
        file_path = request_params['file.path']
        file_size = request_params['file.size']
        # save file to tmp
        today_str = datetime.date.today().strftime("%Y-%m-%d")
        new_file_name = str(uuid.uuid1())
        dir = '%s/%s' % (UPLOAD_FILE_PATH, today_str)
        isExists = os.path.exists(dir)
        if not isExists:
            os.makedirs(dir)
        new_file_path = ''.join([UPLOAD_FILE_PATH, '%s/' % today_str, new_file_name, os.path.splitext(file_name)[-1]])
        with open(new_file_path, 'a') as new_file:
            with open(file_path, 'rb') as f:
                new_file.write(f.read())
        
        orignUrl = ''.join(['/hls/video/', '%s/' % today_str, new_file_name, os.path.splitext(file_name)[-1]])#没切片之前的播放地址
        coverImgUrl = ''.join(['/hls/video/', '%s/' % today_str, new_file_name, '.jpg'])#封面图片下载地址
        coverImgPath = ''.join(['/var/hls/video/', '%s/' % today_str, new_file_name, '.jpg'])#封面图片存储地址
        playTime = getFileTimes(new_file_path)#视频的播放时长
        return_data = json.loads(addVideoToWeibo(orignUrl, coverImgUrl, file_name.split('.')[-1], file_size, new_file_path, playTime))
        
        mdu3 = os.system('sh /home/test/plugflow.sh %s' % new_file_name)
        content = json.dumps({
            'content_type': file_content_type,
            'orignUrl': orignUrl,
            'size': file_size,
            'playTime': playTime,
            'guid': return_data['data']['videoData']['guid'],
            'mdu3': '',
            'coverImgUrl' : coverImgUrl,
            'code' : 0
        })
        response = HttpResponse(content, content_type='application/json; charset=utf-8')
        os.system('ffmpeg -i %s -y -f  image2  -ss 1 -vframes 1  %s' % (new_file_path, coverImgPath))
        THREAD_MANAGER.add_work(function=cutVideo, param=(new_file_name, return_data['data']['videoData']['guid'], '/hls/video/%s/index.m3u8' % new_file_name))
        return response
    except BaseException as e:
        msg = traceback.format_exc()
        single_logger.error(msg)
        content = json.dumps({
            'message' : 'internal error',
            'code' : 91
        })
        response = HttpResponse(content, content_type='application/json; charset=utf-8')
        return response

def verify_to_weibo(request_params):
    email, token = ('', '')
    import urllib
    import urllib2
    for parm in request_params.split('&'):
        if 'email' in parm:
            email = parm.split('=')[-1].strip()
        if 'token' in parm:
            token = parm.split('=')[-1].strip()
    values = {"email":email,"token":token}
    data = urllib.urlencode(values) 
    request = urllib2.Request( '%s?%s' % (VERIFY_VIDEO_TOKEN, data))
    response = urllib2.urlopen(request)
    return_data = json.loads(response.read())
    return return_data["data"]["correct"]

def getFileTimes(filename):   
    from moviepy.editor import VideoFileClip  
    clip = VideoFileClip(filename)  
    return int(clip.duration) 



#把视频相关数据添加到文件表中
def addVideoToWeibo(orignUrl, coverImgUrl, format, length, path, playTime):
    import urllib
    import urllib2
    values = {"orignUrl":orignUrl,"coverImgUrl":coverImgUrl,"format":format,"length":length,"path":path,"playTime":playTime}
    data = urllib.urlencode(values) 
    request = urllib2.Request(ADDVIDEO_WEIBO_URL, data)
    response = urllib2.urlopen(request)
    return response.read()

#视频切片
def cutVideo((fileName, guid, m3u8Url)):
    today_str = datetime.date.today().strftime("%Y-%m-%d")
    os.system('sh /home/test/plugflow.sh %s %s' % (today_str, fileName))
    if os.path.exists('/var%s' % m3u8Url):
        updateVideoToWeibo(guid, m3u8Url)

#把切片好的视频地址更新到视频的文件表
def updateVideoToWeibo(guid, m3u8Url):
    import urllib
    import urllib2
    values = {"guid":guid, "m3u8Url":m3u8Url}
    data = urllib.urlencode(values) 
    request = urllib2.Request(UPDATE_WEIBO_JSONDATA, data)
    response = urllib2.urlopen(request)
    return response.read()
    
'''def timeConvert(size):# 单位换算  
    M, H = 60, 60**2  
    if size < M:  
        return str(size)+'S'  
    if size < H:  
        return '%sM%sS'%(int(size/M),int(size%M))  
    else:  
        hour = int(size/H)  
        mine = int(size%H/M)  
        second = int(size%H%M)  
        tim_srt = '%sH%sM%sS'%(hour,mine,second)  
    return tim_srt  
'''
原文地址:https://www.cnblogs.com/jiangjing/p/8427790.html