Day 24 开发者福音无服务器运算

随着资讯技术普及与推陈布新,基础设施及服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)等等...让不同的使用者可以依照自身的条件与需求选择服务,接着要探访的项目近几年越来越多开发者熟知的无服务器服务,使用者不在需要思考服务器运算环境需要什麽样的规格、作业系统、负载均衡..等等问题,而在阿里云提供什麽样的无服务器架构服务呢?

函数计算(Function Compute,FC)

阿里云FC是一个透过事件触发驱动的全托管运算服务,只要将程序码逻辑布署上去,当有条件触发时才会去执行运算,而未执行触发FC时不会运行,对於成本降低有相当大的帮助

流程示意图:

  • 建立服务
  • 新增function
  • 上传程序码
  • 设定Tigger条件
  • 执行function
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353cSvsWfWauC.png

实务操作FC:

接着我们要利用FC建立一个自动转档的应用,将上传至指定OSS资料夹内的影片转码成hls协议的影音格式并存入另一个OSS资料夹内

架构示意图:
https://ithelp.ithome.com.tw/upload/images/20211006/20140353O7E6jRfudI.png

  1. 在产品导览页找到函数计算服务
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353YfVkxFuM42.png

  2. 点选服务及函数建立服务
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353qAJlTATBm9.png
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353hDmFGIf9gZ.png

  3. 建立服务完成後点选新增函数
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353Ra1Z7pLgWy.png

  4. 下方有提供多样的模板可以套用,因为要使用OSS触发驱动这里选择事件函数
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353yHsdkR11jR.png

  5. 建立函数名称,这里要测试的程序使用的是python3运行,上传程序码 (这里上传包含ffmpeg程序档)
    https://ithelp.ithome.com.tw/upload/images/20211006/201403538D6uKtyzFF.png

目录结构:
ffmpeg
index.py

index.py完整范例程序码:

# -*- coding: utf-8 -*-
import logging
import oss2
import os
import time
import json
import subprocess
from os import walk

logging.getLogger("oss2.api").setLevel(logging.ERROR)
logging.getLogger("oss2.auth").setLevel(logging.ERROR)

OUTPUT_DST = os.environ["OUTPUT_DST"]
DST_TARGET = os.environ["DST_TARGET"]

def get_fileNameExt(filename):
    (fileDir, tempfilename) = os.path.split(filename)
    (shortname, extension) = os.path.splitext(tempfilename)
    return shortname, extension

def get_beijing_time_str(utc_time_stamp):
    local_time = time.localtime(utc_time_stamp + 8*3600)
    data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
    data_secs = (utc_time_stamp - int(utc_time_stamp)) * 1000
    beijing_time_str = "%s.%03d" % (data_head, data_secs)
    return beijing_time_str

def handler(event, context):
    utc_now = time.time()
    evt = json.loads(event)
    evt = evt["events"]
    oss_bucket_name = evt[0]["oss"]["bucket"]["name"]
    object_key = evt[0]["oss"]["object"]["key"]
    size = evt[0]["oss"]["object"]["size"]
    shortname, extension = get_fileNameExt(object_key)
    M_size = round(size / 1024.0 / 1024.0, 2)
    json_log = {
        "request_id": context.request_id,
        "video_name": object_key,
        "video_format": extension[1:],
        "size": M_size,
        "start_time": get_beijing_time_str(utc_now),
        "processed_video_location": OUTPUT_DST,
    }
    print(json.dumps(json_log))
   
    creds = context.credentials
    auth = oss2.StsAuth(creds.accessKeyId, creds.accessKeySecret, creds.securityToken)
    oss_client = oss2.Bucket(auth, 'oss-%s-internal.aliyuncs.com' % context.region, oss_bucket_name)
    input_path = oss_client.sign_url('GET', object_key, 6 * 3600)
    transcoded_filepath = '/tmp/' + shortname + DST_TARGET
    if os.path.exists(transcoded_filepath):
        os.remove(transcoded_filepath)
    # cmd = ["/code/ffmpeg", "-y", "-i", input_path, "-vf", "scale=640:480", "-b:v", "800k", "-bufsize", "800k", transcoded_filepath]
    # cmd = ["/code/ffmpeg", "-y", "-i", input_path, "-b:v", "1M", "-g", "60", "-hls_time", "2", "-hls_list_size", "0", "-hls_segment_size", "500000",  transcoded_filepath]
    cmd = ["/code/ffmpeg", "-y", "-i", input_path, "-profile:v", "baseline", "-level", "3.0", "-start_number", "0", "-hls_time", "10", "-hls_list_size", "0", transcoded_filepath]
    
    try:
        result = subprocess.run(
            cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
    except subprocess.CalledProcessError as exc:
        err_ret = {
            'request_id': context.request_id,
            'returncode': exc.returncode,
            'cmd': exc.cmd,
            'output': exc.output.decode(),
            'event': evt,
        }
        if exc.stderr:
            err_ret['stderr'] = exc.stderr.decode()
        if exc.stdout:
            err_ret['stdout'] = exc.stdout.decode()
        print(json.dumps(err_ret))
        # if transcode fail, send event to mns queue or insert in do db
        # ...
        raise Exception(context.request_id + " transcode failure")
        return

    filenames = next(walk('/tmp'), (None, None, []))[2]

    for f in filenames:
        if f.find(shortname) != -1:
            oss_client.put_object_from_file(
                os.path.join(OUTPUT_DST, f), ('/tmp/'+ f) )
    
##    oss_client.put_object_from_file(
##        os.path.join(OUTPUT_DST, shortname + DST_TARGET), transcoded_filepath)
    
    # if transcode succ, send event to mns queue or insert in do db
    # ...

    if os.path.exists(transcoded_filepath):
        os.remove(transcoded_filepath)
    
    return "ok"

ffmpeg包为预设的设定,如找不到想测试可以联络笔者(嘘)

  1. 建立好函数後,会到程序执行页面,测试执行发现报错
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353zZJayrTVQr.png
    https://ithelp.ithome.com.tw/upload/images/20211006/201403537MLuNbwRzE.png

  2. 这里发现忘记先建立OSS触发条件;权限,建立触发器:

  • 选择对象储存触发器
  • 需要触发的OSS Bucket
  • 触发事件
  • 触发规则
    最後要授权给OSS触发器的权限角色,没有角色则可以直接新建授权
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353JRhgf6DLAK.png
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353VaM1GEVS1d.png
  1. 在OSS Bucket下建立资料夹/vedio/inputs、/vedio/outputs
    https://ithelp.ithome.com.tw/upload/images/20211006/201403530D1RRcs6uW.png

  2. 准备完成後,测试上传影音档案,查看/vedio/inputs上传成功
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353V7XiwfXyoJ.png
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353DHh1wu4MPg.png

  3. 接着打开/vedio/outputs验证mp4转码与m3u8成功,测试也能正常播放 (本影片仅测试使用)
    https://ithelp.ithome.com.tw/upload/images/20211006/20140353KUtobNwGUT.png
    https://ithelp.ithome.com.tw/upload/images/20211006/201403537FqHigIgkH.png

本篇的小应用就到这里结束,对於经常需要使用影音串流的使用者可以透过FC快速完成转码工作并透过无服务器特性不浪费使用资源,而运用FC能够让开发者集思广益建立更多发挥创意的应用!


<<:  [Day 21]从零开始学习 JS 的连续-30 Days---阵列操作介绍 (上篇)

>>:  DAY21 - 网页可以操作电脑里的档案?!本地端档案覆写 - The File System Access API

[Lesson17] MVP

MVP架构: Model — 管理资料来源。例如:SharedPreferences、Room、呼叫...

Day29. 虽然今年是2021,但我们要做2048(3)

来到2048的最後一天!看看这麽多的删除线!虽然可能我们不一定能清光我们购物网站上的愿望清单,但是今...

假名数据(Pseudonymized data)

-化名(Pseudonymization) 假名(Pseudonymized)数据可以通过添加信息...

DAY05 - [CSS] 三角型,来个推荐标签吧!

今日文章目录 > - 三角型使用情境 > - 用CSS画三角型 > - 参考资料...

[Day24] React - 浅谈SPA(single-page applications)

在开始React之旅前,必须先了解一下什麽是SPA。 相较於过去使用的多页式(MPA)网页开发,大多...