您可以通过函数计算、对象存储OSS和FFmpeg实现弹性高可用的处理音视频。本文以Python语言为例,介绍如何基于Serverless Devs开发工具处理音视频,获取音视频信息例如Meta信息、时长等。您也可以按需修改函数的示例代码实现二次开发。

背景信息

FFmpeg是一套可以记录、转换数字音视频,并将其转化为流的开源计算机程序。FFmpeg采用LGPL或GPL许可证,提供了录制、转换和流化音视频的完整解决方案,包括先进的音视频编解码库libavcodec,并且保证了高可移植性和编解码质量。详细信息,请参见FFmpeg
本文介绍的示例模板中包含以下主题:
示例名称 描述
GetMediaMeta 获取音视频的Meta信息。
GetDuration 获取音视频的时长。
TranscodeMaster、TranscodeWorker 并行转换音视频。
GetSprites 将视频制作成雪碧图。
VideoWatermark 添加文字水印、静态图片水印和动态GIF水印。
AudioConvert 转换音视频格式。
VideoGif 将Video格式提取成GIF格式。

前提条件

使用Serverless Devs部署应用

  1. 执行以下命令,初始化项目。
    s init devsapp/ffmpeg-app -d ffmpeg-app

    -d用于指定生成的目录的名称。

    输出示例:
     Serverless Awesome: https://github.com/Serverless-Devs/package-awesome
    
     file decompression completed
     please select credential alias default
    
         _______  _______  __   __  _______  _______  _______
        |       ||       ||  |_|  ||       ||       ||       |
        |    ___||    ___||       ||    _  ||    ___||    ___|
        |   |___ |   |___ |       ||   |_| ||   |___ |   | __
        |    ___||    ___||       ||    ___||    ___||   ||  |
        |   |    |   |    | ||_|| ||   |    |   |___ |   |_| |
        |___|    |___|    |_|   |_||___|    |_______||_______|
    
    
        Welcome to the ffmpeg-app application
         This application requires to open these services:
             FC : https://fc.console.aliyun.com/
         This application can help you quickly deploy the ffmpeg-app project.
         The application uses FC component:https://github.com/devsapp/fc
         The application homepage: https://github.com/devsapp/ffmpeg-app
    
    
    ‍ Thanks for using Serverless-Devs
     You could [cd /test/ffmpeg-app] and enjoy your serverless journey!
    ️ If you need help for this example, you can use [s -h] after you enter folder.
     Document Star:https://github.com/Serverless-Devs/Serverless-Devs
  2. 执行以下命令,进入项目目录。
    cd ffmpeg-app
  3. 可选:按需修改项目目录中的代码示例,实现您的业务逻辑。
  4. 执行以下命令,部署项目。
    s deploy -y
    说明 如果您只需要部署该项目内的某个功能,例如需要部署GetMediaMeta功能获取音视频的Meta信息。请执行以下命令:
    s GetMediaMeta deploy

    当您需要部署其他功能时,请将GetMediaMeta修改为其他功能的名称。

    输出示例:
    [2021-11-25T17:35:56.524] [INFO ] [S-CLI] - Start ...
    [2021-11-25T17:35:56.529] [INFO ] [S-CLI] - It is detected that your project has the following projects < AudioConvert,GetMediaMeta,TranscodeMaster,TranscodeWorker,GetDuration,VideoGif,GetSprites,VideoWatermark > to be execute
    [2021-11-25T17:35:56.530] [INFO ] [S-CLI] - Start executing project AudioConvert
    [2021-11-25T17:35:57.725] [INFO ] [FC-DEPLOY] - Using region: cn-qingdao
    [2021-11-25T17:35:57.725] [INFO ] [FC-DEPLOY] - Using access alias: default
    [2021-11-25T17:35:57.726] [INFO ] [FC-DEPLOY] - Using accessKeyID: LTAI4G4cwJkK4Rza6xd9****
    [2021-11-25T17:35:57.726] [INFO ] [FC-DEPLOY] - Using accessKeySecret: eCc0GxSpzfq1DVspnqqd6nmYNN****
     Using fc deploy type: sdk, If you want to deploy with pulumi, you can [s cli fc-default set deploy-type pulumi] to switch.
     ......
    
    There is auto config in the service: FcOssFFmpeg
    
    ......
    AudioConvert:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       AudioConvert
        runtime:    python3
        handler:    index.handler
        memorySize: 256
        timeout:    600
    GetMediaMeta:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       GetMediaMeta
        runtime:    python3
        handler:    index.handler
        memorySize: 1024
        timeout:    600
    TranscodeMaster:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       TranscodeMaster
        runtime:    python3
        handler:    index.handler
        memorySize: 1024
        timeout:    600
    TranscodeWorker:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       TranscodeWorker
        runtime:    python3
        handler:    index.handler
        memorySize: 3072
        timeout:    600
    GetDuration:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       GetDuration
        runtime:    python3
        handler:    index.handler
        memorySize: 256
        timeout:    600
    VideoGif:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       VideoGif
        runtime:    python3
        handler:    index.handler
        memorySize: 512
        timeout:    600
    GetSprites:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       GetSprites
        runtime:    python3
        handler:    index.handler
        memorySize: 512
        timeout:    600
    VideoWatermark:
      region:   cn-qingdao
      service:
        name: FcOssFFmpeg
      function:
        name:       VideoWatermark
        runtime:    python3
        handler:    index.handler
        memorySize: 256
        timeout:    600
  5. 调试示例函数。

    执行以下命令,调试GetMediaMeta函数,获取音视频的Meta信息。

    s GetMediaMeta invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4"}'

    参数说明

    • bucket_name:Bucket名称。
    • object_key:需获取音视频Meta信息的文件的名称。

    输出示例

    [2021-11-26T14:19:02.045] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    FunctionCompute python3 runtime inited.
    FC Invoke Start RequestId: dda964e0-82b6-452a-b849-6b0b835f****
    2021-11-26T06:19:04.688Z dda964e0-82b6-452a-b849-6b0b835f**** [INFO] current Function [handler] excute time is 0.23 seconds
    FC Invoke End RequestId: dda964e0-82b6-452a-b849-6b0b835f****
    
    Duration: 1238.78 ms, Billed Duration: 1239 ms, Memory Size: 1024 MB, Max Memory Used: 118.39 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    {
        "format": {
            "bit_rate": "17024829",
            "duration": "110.037333",
            "filename": "http://test-bucket.oss-cn-qingdao-internal.aliyuncs.com/a.mp4......",
            "format_long_name": "QuickTime / MOV",
            "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
            "nb_programs": 0,
            "nb_streams": 2,
            "probe_score": 100,
            "size": "234170850",
            "start_time": "0.000000",
            "tags": {
                "compatible_brands": "mp42mp41",
                "creation_time": "2020-09-05T06:03:49.000000Z",
                "major_brand": "mp42",
                "minor_version": "0"
            }
        },
        "streams": [
            {
                "avg_frame_rate": "25/1",
                "bit_rate": "16708594",
                "bits_per_raw_sample": "8",
                "chroma_location": "left",
                "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
                "codec_name": "h264",
                "codec_tag": "0x31637661",
                "codec_tag_string": "avc1",
                "codec_time_base": "1/50",
                "codec_type": "video",
                "coded_height": 1088,
                "coded_width": 1920,
                "color_primaries": "bt709",
                "color_range": "tv",
                "color_space": "bt709",
                "color_transfer": "bt709",
                "disposition": {
                    "attached_pic": 0,
                    "clean_effects": 0,
                    "comment": 0,
                    "default": 1,
                    "dub": 0,
                    "forced": 0,
                    "hearing_impaired": 0,
                    "karaoke": 0,
                    "lyrics": 0,
                    "original": 0,
                    "timed_thumbnails": 0,
                    "visual_impaired": 0
                },
                "duration": "110.000000",
                "duration_ts": 2750000,
                "has_b_frames": 1,
                "height": 1080,
                "index": 0,
                "is_avc": "true",
                "level": 41,
                "nal_length_size": "4",
                "nb_frames": "2750",
                "pix_fmt": "yuv420p",
                "profile": "Main",
                "r_frame_rate": "25/1",
                "refs": 1,
                "start_pts": 0,
                "start_time": "0.000000",
                "tags": {
                    "creation_time": "2020-09-05T06:03:49.000000Z",
                    "encoder": "AVC Coding",
                    "handler_name": "\u001fMainconcept Video Media Handler",
                    "language": "eng"
                },
                "time_base": "1/25000",
                "width": 1920
            },
            {
                "avg_frame_rate": "0/0",
                "bit_rate": "317375",
                "bits_per_sample": 0,
                "channel_layout": "stereo",
                "channels": 2,
                "codec_long_name": "AAC (Advanced Audio Coding)",
                "codec_name": "aac",
                "codec_tag": "0x6134706d",
                "codec_tag_string": "mp4a",
                "codec_time_base": "1/48000",
                "codec_type": "audio",
                "disposition": {
                    "attached_pic": 0,
                    "clean_effects": 0,
                    "comment": 0,
                    "default": 1,
                    "dub": 0,
                    "forced": 0,
                    "hearing_impaired": 0,
                    "karaoke": 0,
                    "lyrics": 0,
                    "original": 0,
                    "timed_thumbnails": 0,
                    "visual_impaired": 0
                },
                "duration": "110.000000",
                "duration_ts": 5280000,
                "index": 1,
                "max_bit_rate": "417750",
                "nb_frames": "5158",
                "profile": "LC",
                "r_frame_rate": "0/0",
                "sample_fmt": "fltp",
                "sample_rate": "48000",
                "start_pts": 0,
                "start_time": "0.000000",
                "tags": {
                    "creation_time": "2020-09-05T06:03:49.000000Z",
                    "handler_name": "#Mainconcept MP4 Sound Media Handler",
                    "language": "eng"
                },
                "time_base": "1/48000"
            }
        ]
    }
    End of method: invoke
    

    执行以下命令,调试函数,获取音视频的时长。

    s GetDuration invoke -e '{"bucket_name": "bucket-name","object_key": "a.mp4"}'

    参数说明

    • bucket_name:Bucket名称。
    • object_key:需获取时长的文件的名称。
    输出示例
    [2021-11-26T14:21:48.877] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    FunctionCompute python3 runtime inited.
    FC Invoke Start RequestId: 6bb9ecae-7f53-4efb-afea-7614ef87****
    2021-11-26T06:21:50.273Z 6bb9ecae-7f53-4efb-afea-7614ef87**** [INFO] current Function [handler] excute time is 0.17 seconds
    FC Invoke End RequestId: 6bb9ecae-7f53-4efb-afea-7614ef87****
    
    Duration: 754.63 ms, Billed Duration: 755 ms, Memory Size: 256 MB, Max Memory Used: 61.21 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    110.037333
    
    End of method: invoke

    • 调试TranscodeMaster

      执行以下命令,调试TranscodeMaster函数,对目标视频实现并行转码。

      s TranscodeMaster invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4","dst_type" : ".flv", "segment_time_seconds": 30, "output_dir" : "output/"}'

      参数说明

      • bucket_name:Bucket名称。
      • object_key:需转码的文件的名称。
      • dst_type:转码后文件的格式。
      • segment_time_seconds:目标视频切片的分段时间。
      • output_dir:转码后视频存储在对象存储中的位置。
      输出示例
      [2021-11-30T10:09:27.690] [INFO ] [S-CLI] - Start ...
      ========= FC invoke Logs begin =========
      FunctionCompute python3 runtime inited.
      FC Invoke Start RequestId: 00e1d66a-e118-46ed-acf3-603bd37eb674
      ......
      FC Invoke End RequestId: 00e1d66a-e118-46ed-acf3-603bd37eb674
      
      Duration: 29298.53 ms, Billed Duration: 29299 ms, Memory Size: 1024 MB, Max Memory Used: 320.33 MB
      ========= FC invoke Logs end =========
      
      FC Invoke Result:
      ok
      
      End of method: invoke

    • 调试TranscodeWorker

      执行以下命令,调用TranscodeWorker函数,对目标视频实现并行转码。

      s TranscodeWorker invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "dst_type":".wav"}'

      参数说明

      • bucket_name:Bucket名称。
      • object_key:需转码的文件的名称。
      • output_dir:转码后视频存储在对象存储中的位置。
      • dst_type:转码后文件的格式。
      输出示例
      [2021-11-26T16:07:42.585] [INFO ] [S-CLI] - Start ...
      ========= FC invoke Logs begin =========
      FunctionCompute python3 runtime inited.
      FC Invoke Start RequestId: 1b427831-e10f-4c2b-b780-9b504c29aa67
      2021-11-26T08:07:44.684Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] b'{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "dst_type":".wav"}'
      2021-11-26T08:07:51.642Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] Uploaded /tmp/transcoded_a.wav to output/transcoded_a.wav
      2021-11-26T08:07:51.642Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] current Function [handler] excute time is 6.96 seconds
      FC Invoke End RequestId: 1b427831-e10f-4c2b-b780-9b504c29aa67
      
      Duration: 7876.26 ms, Billed Duration: 7877 ms, Memory Size: 3072 MB, Max Memory Used: 119.06 MB
      ========= FC invoke Logs end =========
      
      FC Invoke Result:
      ok
      
      
      End of method: invoke

    执行以下命令,调试GetSprites函数,将视频制作成雪碧图。

    s GetSprites invoke -e '{"bucket_name": "test-bucket","object_key": "aclear.mp4", "output_dir" : "output/", "tile": "3*4"}'

    参数说明

    • bucket_name:Bucket的名称。
    • object_key:需制作成雪碧图的文件的名称。
    • output_dir:转码后的视频存储在Bucket内的位置。
    • tile:雪碧图的行和列。
    • (可选)start:开始制作雪碧图的时间。默认值为0。
    • (可选)duration:基于Start参数后多长时间的视频内开始截图。例如start取值为10,duration取值为20,表示截取10s到30s内的视频。
    • (可选)itsoffset:表示流偏移命令,延迟时间。默认值为0。该参数需要和start、interval一起使用,示例如下:
      • start取值为0,interval取值为10,itsoffset取值为0,则截图的描述为5、15和25等。
      • start取值为0,interval取值为10,itsoffset取值为1,则截图的描述为4、14和24等。
      • start取值为0,interval取值为10,itsoffset取值为-1,则截图的描述为6、16和26等。
      • start取值为0,interval取值为10,itsoffset取值为4.999,则截图的描述为0、10和20等。
       
      说明 当该参数取值为5时,会丢失0秒时的图片,建议您将该参数设置为4.999。
       
    • (可选)scale:截图的大小。默认比例为-1:-1。该参数可选
    • (可选)interval:表示时隔几秒截取一次视频。默认值为1。
    • (可选)padding:表示图片的间隔。默认值为0。
    • (可选)color:表示雪碧图的背景颜色。默认颜色为黑色。
    • (可选)dst_type:表示生成雪碧图的图片格式。默认为JPG。取值为JPG和PNG。
    输出示例
    [2021-11-26T16:07:42.585] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    FunctionCompute python3 runtime inited.
    FC Invoke Start RequestId: 1b427831-e10f-4c2b-b780-9b504c29aa67
    2021-11-26T08:07:44.684Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] b'{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "dst_type":".wav"}'
    2021-11-26T08:07:51.642Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] Uploaded /tmp/transcoded_a.wav to output/transcoded_a.wav
    2021-11-26T08:07:51.642Z 1b427831-e10f-4c2b-b780-9b504c29aa67 [INFO] current Function [handler] excute time is 6.96 seconds
    FC Invoke End RequestId: 1b427831-e10f-4c2b-b780-9b504c29aa67
    
    Duration: 7876.26 ms, Billed Duration: 7877 ms, Memory Size: 3072 MB, Max Memory Used: 119.06 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    ok
    
    
    End of method: invoke

    执行以下命令,调试VideoWatermark函数,给视频添加水印。

    s VideoWatermark invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "vf_args" : "drawtext=fontfile=/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc:text='hello函数计算':x=100:y=50:fontsize=24:fontcolor=red"}'

    参数说明

    • bucket_name:Bucket的名称。
    • object_key:需添加水印的文件的名称。
    • output_dir:转码后的视频存储在Bucket内的位置。
    • vf_args:表示文字水印或静态图片水印。
    • filter_complex_args:表示动态图片水印。当设置该参数与vf_args同时设置时,则默认忽略vf_args的参数信息。
    输出示例
    [2021-11-26T15:20:24.396] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    static-master/target/lib ......
    ......
    FC Invoke End RequestId: 31ecddfa-4e41-44bb-9489-00708b07****
    
    Duration: 1302.08 ms, Billed Duration: 1303 ms, Memory Size: 256 MB, Max Memory Used: 256.00 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    ok
    
    
    End of method: invoke

    执行以下命令,调试AudioConvert函数,转换音频格式。

    s AudioConvert invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "dst_type":".wav", "ac":"1", "ar":"4000"}'

    参数说明

    • bucket_name:Bucket的名称。
    • object_key:需转换音频格式的文件的名称。
    • output_dir:转码后的视频存储在Bucket内的位置。
    • dst_type:转换后文件的格式。
    • (可选)ac:指定声道数。
    • (可选)ar:指定采样率。
    输出示例
    [2021-11-26T16:04:16.293] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    ......
    2021-11-26T08:04:18.520Z 2fc578cd-8787-4681-ab21-a3f6b4ab1e2a [ERROR] returncode:1
    ......
    Duration: 1156.09 ms, Billed Duration: 1157 ms, Memory Size: 256 MB, Max Memory Used: 88.23 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    ok
    
    
    End of method: invoke

    执行以下命令,调试VideoGif函数,将视频转化为GIF。

    s VideoGif invoke -e '{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "vframes": "5", "start": "0",  "duration": "2"}'

    参数说明

    • bucket_name:Bucket的名称。
    • object_key:需转换为GIF格式的文件的名称。
    • output_dir:转码后的视频存储在对象存储中的位置。
    • (可选)vframes:基于start参数后多长时间的视频内开始转换视频。
    • (可选)start:开始转换的时间。默认值为0。
    • (可选)duration:基于start参数后多长时间的视频内开始转换视频。
     
    说明 当同时设置了durationvframes参数时,以duration的参数信息为准。当这两个参数都未设置时,则默认将整个视频转换为GIF格式。
     
    输出示例
    [2021-11-26T15:27:26.647] [INFO ] [S-CLI] - Start ...
    ========= FC invoke Logs begin =========
    FunctionCompute python3 runtime inited.
    FC Invoke Start RequestId: a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb
    2021-11-26T07:27:28.279Z a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb [INFO] b'{"bucket_name": "test-bucket","object_key": "a.mp4", "output_dir" : "output/", "vframes": "5", "start": "0",  "duration": "2"}'
    2021-11-26T07:27:28.280Z a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb [INFO] cmd = ffmpeg -y -ss 0 -t 2 -accurate_seek -i ......
    2021-11-26T07:27:30.150Z a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb [INFO] Uploaded /tmp/a.gif to output/a.gif
    2021-11-26T07:27:30.151Z a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb [INFO] current Function [handler] excute time is 1.87 seconds
    FC Invoke End RequestId: a49fc8b4-ee8f-4e8b-9923-b8b41ced47cb
    
    Duration: 2495.95 ms, Billed Duration: 2496 ms, Memory Size: 512 MB, Max Memory Used: 85.32 MB
    ========= FC invoke Logs end =========
    
    FC Invoke Result:
    ok
    
    End of method: invoke