Instans Function Compute yang dipercepat GPU memungkinkan Anda menjalankan transkoding video berbasis FFmpeg secara skala besar tanpa perlu mengelola driver GPU, versi CUDA, atau kluster perangkat keras. Panduan ini akan memandu Anda melalui proses penyebaran fungsi transkoding yang dipercepat GPU menggunakan Serverless Devs dan Python, dengan contoh konversi dari MP4 ke FLV.
Kapan menggunakan akselerasi GPU
Akselerasi GPU memberikan manfaat paling signifikan ketika pekerjaan transkoding diperkirakan berjalan lebih dari beberapa menit atau ketika Anda memerlukan beberapa aliran output dari satu input. Skenario spesifik meliputi:
Transkoding 1080p dan resolusi lebih tinggi: Video H.264 1080p berdurasi 2 menit membutuhkan waktu lebih dari 3 menit pada CPU tetapi kurang dari 10 detik pada GPU — percepatan hingga 20x.
Output multi-aliran (1:N): Menghasilkan 3 resolusi output secara simultan membutuhkan waktu kurang dari 6 menit pada CPU tetapi sekitar 45 detik pada GPU.
Pipeline sensitif latensi: Streaming langsung sosial, kelas daring, dan telemedisin memerlukan pengiriman secara real-time atau mendekati real-time.
Untuk pekerjaan yang selesai jauh di bawah satu menit pada CPU, overhead penyediaan instans GPU mungkin lebih besar daripada manfaat percepatannya.
Format codec yang didukung
Instans yang dipercepat GPU didasarkan pada arsitektur Turing dan menggunakan GPU NVIDIA T4.
Encoding
| Format |
|---|
| H.264 (AVCHD) YUV 4:2:0 |
| H.264 (AVCHD) YUV 4:4:4 |
| H.264 (AVCHD) Lossless |
| H.265 (HEVC) 4K YUV 4:2:0 |
| H.265 (HEVC) 4K YUV 4:4:4 |
| H.265 (HEVC) 4K Lossless |
| H.265 (HEVC) 8K |
| HEVC 10-bit |
| HEVC B-frame |
Decoding
| Format | Bit depths |
|---|---|
| MPEG-1 | 8-bit |
| MPEG-2 | 8-bit |
| VC-1 | 8-bit |
| VP8 | 8-bit |
| VP9 | 8-bit, 10-bit, 12-bit |
| H.264 (AVCHD) | 8-bit, 10-bit, 12-bit |
| H.265 (HEVC) 4:2:0 | 8-bit, 10-bit, 12-bit |
| *H.265 (HEVC) 4:4:4 | 8-bit, 10-bit, 12-bit |
Tolok ukur kinerja
Pengujian berikut menggunakan video sumber H.264 berdurasi 2 menit 5 detik (1920x1080, 25 fps, 4.085 Kb/s; audio: aac (LC), 44.100 Hz, stereo, fltp) pada mesin dengan CPU identik (Xeon® Platinum 8163 4C, RAM 16 GB) — satu dengan GPU T4, satu tanpa GPU. Versi FFmpeg: git-2020-08-12-1201687.
Transkoding 1:1 (1 input, 1 output)
| Resolusi | Tanpa GPU | Dengan GPU |
|---|---|---|
| H264 1920x1080 (Full HD, 1080p) | 3 menit 19,3 dtk | 9,4 dtk |
| H264 1280x720 (HD, 720p) | 2 menit 3,7 dtk | 5,8 dtk |
| H264 640x480 (480p) | 1 menit 1,0 dtk | 5,8 dtk |
| H264 480x360 (360p) | 44,4 dtk | 5,7 dtk |
Transkoding 1:N (1 input, 3 output: 1080p + 720p + 480p)
| Tanpa GPU | Dengan GPU |
|---|---|
| 5 menit 58,7 dtk | 45,3 dtk |
Cara kerja
Fungsi berjalan di dalam kontainer kustom yang dibangun berdasarkan gambar FFmpeg yang telah diaktifkan NVIDIA. Saat dipanggil, fungsi tersebut:
Mengunduh video sumber dari bucket Object Storage Service (OSS).
Menjalankan FFmpeg untuk mentranskode video. Dalam mode GPU, FFmpeg memindahkan proses decoding dan encoding ke perangkat keras NVIDIA menggunakan CUDA — flag
-hwaccel cuda -hwaccel_output_format cudamenyimpan frame yang telah didekode di memori GPU, sehingga menghindari transfer CPU-GPU sebelum proses encoding. Flagh264_nvencmenginstruksikan FFmpeg untuk menggunakan encoder perangkat keras NVIDIA untuk output H.264, bukan encoder perangkat lunak. Tanpa flag tersebut, FFmpeg akan kembali menggunakan encoding perangkat lunak pada CPU.Mengunggah hasil transkoding ke OSS.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Keanggotaan grup DingTalk (ID grup: 11721331). Untuk bergabung, berikan nama organisasi Anda, ID akun Alibaba Cloud, wilayah target (misalnya, China (Shenzhen)), dan detail kontak.
Instans Container Registry Edisi Perusahaan di wilayah yang sama dengan instans yang dipercepat GPU Anda. Edisi Personal dapat digunakan, tetapi Edisi Perusahaan direkomendasikan. Lihat Buat instans Container Registry Edisi Perusahaan.
Namespace dan repository image di instans tersebut. Lihat Buat namespace dalam dokumentasi Container Registry. Kemudian buat repository image di instans yang sama.
Binari FFmpeg yang dikompilasi dengan dukungan GPU NVIDIA. Gunakan salah satu berikut:
(Direkomendasikan) Gambar Docker yang telah dibuat sebelumnya: willprice/nvidia-ffmpeg. Atau, gunakan jrottenberg/ffmpeg.
Dikompilasi secara manual — lihat Panduan kompilasi FFmpeg NVIDIA.
Berkas audio dan video yang telah diunggah ke bucket OSS di wilayah yang sama. Fungsi memerlukan akses baca dan tulis ke objek bucket tersebut. Lihat Unggah objek untuk instruksi pengunggahan dan Ubah ACL bucket untuk pengaturan izin.
Perintah transkoding FFmpeg
Semua contoh di bawah menggunakan gambar Docker willprice/nvidia-ffmpeg.
Tanpa akselerasi GPU
Output tunggal (1:1)
docker run --rm -it --volume $PWD:/workspace --runtime=nvidia willprice/nvidia-ffmpeg \
-y -i input.mp4 -c:v h264 -vf scale=1920:1080 -b:v 5M output.mp4Output ganda (1:N)
docker run --rm -it --volume $PWD:/workspace --runtime=nvidia willprice/nvidia-ffmpeg \
-y -i input.mp4 \
-c:a copy -c:v h264 -vf scale=1920:1080 -b:v 5M output_1080.mp4 \
-c:a copy -c:v h264 -vf scale=1280:720 -b:v 5M output_720.mp4 \
-c:a copy -c:v h264 -vf scale=640:480 -b:v 5M output_480.mp4Dengan akselerasi GPU
Output tunggal (1:1)
docker run --rm -it --volume $PWD:/workspace --runtime=nvidia willprice/nvidia-ffmpeg \
-y -hwaccel cuda -hwaccel_output_format cuda \
-i input.mp4 -c:v h264_nvenc -vf scale_cuda=1920:1080:1:4 -b:v 5M output.mp4Output ganda (1:N)
docker run --rm -it --volume $PWD:/workspace --runtime=nvidia willprice/nvidia-ffmpeg \
-y -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 \
-c:a copy -c:v h264_nvenc -vf scale_npp=1920:1080 -b:v 5M output_1080.mp4 \
-c:a copy -c:v h264_nvenc -vf scale_npp=1280:720 -b:v 5M output_720.mp4 \
-c:a copy -c:v h264_nvenc -vf scale_npp=640:480 -b:v 5M output_480.mp4Parameter utama
| Parameter | Deskripsi |
|---|---|
-hwaccel cuda | Memilih akselerator perangkat keras CUDA untuk decoding |
-hwaccel_output_format cuda | Menyimpan frame yang telah didekode di memori GPU, menghindari transfer CPU-GPU sebelum encoding |
-c:v h264_nvenc | Menggunakan encoder H.264 perangkat keras NVIDIA |
-c:a copy | Menyalin aliran audio tanpa melakukan re-encoding |
-b:v 5M | Mengatur bitrate output menjadi 5 Mb/s |
Sebarkan fungsi GPU dengan Serverless Devs
Sebelum memulai, instal Serverless Devs dan Docker. Lalu ikuti langkah-langkah untuk mengonfigurasi Serverless Devs dengan kredensial Anda.
Prosedur
Buat proyek.
fc-gpu-prj ├── code │ ├── app.py # Kode fungsi │ └── Dockerfile # Dockerfile gambar ├── README.md └── s.yaml # Konfigurasi penyebaranStruktur proyek yang dihasilkan:
fc-gpu-prj ├── code │ ├── app.py # Kode fungsi │ └── Dockerfile # Dockerfile gambar ├── README.md └── s.yaml # Konfigurasi penyebaranMasuk ke direktori proyek.
cd fc-gpu-prjEdit file konfigurasi. s.yaml — perbarui wilayah, nama layanan, dan URI gambar kontainer sesuai lingkungan Anda. Parameter utama terkait GPU adalah
instanceType: fc.gpu.tesla.1dangpuMemorySize: 8192.edition: 1.0.0 name: container-demo access: default vars: region: cn-shenzhen services: customContainer-demo: component: devsapp/fc props: region: ${vars.region} service: name: tgpu_ffmpeg_service internetAccess: true function: name: tgpu_ffmpeg_func description: test gpu for ffmpeg handler: not-used timeout: 600 caPort: 9000 instanceType: fc.gpu.tesla.1 gpuMemorySize: 8192 cpu: 4 memorySize: 16384 diskSize: 512 runtime: custom-container customContainerConfig: # Prasyarat: # 1. Buat namespace "demo" dan repository "gpu-transcoding_s" di Container Registry. # 2. Tingkatkan tag (misalnya, v0.1 -> v0.2) saat memperbarui dan menyebarkan ulang. image: registry.cn-shanghai.aliyuncs.com/demo/gpu-transcoding_s:v0.1 codeUri: ./codeUntuk daftar lengkap parameter YAML, lihat Spesifikasi YAML. app.py — fungsi ini mengunduh video sumber dari OSS, mentranskode dengan FFmpeg (menggunakan GPU atau CPU berdasarkan header
TRANS-MODE), lalu mengunggah hasilnya kembali ke OSS. Ganti nilai placeholdersrc_urldandst_urldengan URL objek OSS aktual Anda.# -*- coding: utf-8 -*- from __future__ import print_function from http.server import HTTPServer, BaseHTTPRequestHandler import json import sys import logging import os import time import urllib.request import subprocess class Resquest(BaseHTTPRequestHandler): def download(self, url, path): print("enter download:", url) f = urllib.request.urlopen(url) with open(path, "wb") as local_file: local_file.write(f.read()) def upload(self, url, path): print("enter upload:", url) headers = { 'Content-Type': 'application/octet-stream', 'Content-Length': os.stat(path).st_size, } req = urllib.request.Request(url, open(path, 'rb'), headers=headers, method='PUT') urllib.request.urlopen(req) def trans(self, input_path, output_path, enable_gpu): print("enter trans input:", input_path, " output:", output_path, " enable_gpu:", enable_gpu) cmd = ['ffmpeg', '-y', '-i', input_path, "-c:a", "copy", "-c:v", "h264", "-b:v", "5M", output_path] if enable_gpu: cmd = ["ffmpeg", "-y", "-hwaccel", "cuda", "-hwaccel_output_format", "cuda", "-i", input_path, "-c:v", "h264_nvenc", "-b:v", "5M", output_path] try: subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) except subprocess.CalledProcessError as exc: print('\nreturncode:{}'.format(exc.returncode)) print('\ncmd:{}'.format(exc.cmd)) print('\noutput:{}'.format(exc.output)) print('\nstderr:{}'.format(exc.stderr)) print('\nstdout:{}'.format(exc.stdout)) def trans_wrapper(self, enable_gpu): src_url = "https://your.domain/input.mp4" # Ganti dengan URL objek OSS Anda (akses baca diperlukan) dst_url = "https://your.domain/output.flv" # Ganti dengan URL objek OSS Anda (akses tulis diperlukan) src_path = "/tmp/input_c.flv" dst_path = "/tmp/output_c.mp4" if enable_gpu: src_url = "https://your.domain/input.mp4" # Ganti dengan URL objek OSS Anda (akses baca diperlukan) dst_url = "https://your.domain/output.flv" # Ganti dengan URL objek OSS Anda (akses tulis diperlukan) src_path = "/tmp/input_g.flv" dst_path = "/tmp/output_g.mp4" local_time = time.time() self.download(src_url, src_path) download_time = time.time() - local_time local_time = time.time() self.trans(src_path, dst_path, enable_gpu) trans_time = time.time() - local_time local_time = time.time() self.upload(dst_url, dst_path) upload_time = time.time() - local_time data = {'result':'ok', 'download_time':download_time, 'trans_time':trans_time, 'upload_time':upload_time} self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(data).encode()) def pong(self): data = {"function":"trans_gpu"} self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(data).encode()) def dispatch(self): mode = self.headers.get('TRANS-MODE') if mode == "ping": self.pong() elif mode == "gpu": self.trans_wrapper(True) elif mode == "cpu": self.trans_wrapper(False) else: self.pong() def do_GET(self): self.dispatch() def do_POST(self): self.dispatch() if __name__ == '__main__': host = ('0.0.0.0', 9000) server = HTTPServer(host, Resquest) print("Starting server, listen at: %s:%s" % host) server.serve_forever()Dockerfile — membangun gambar kontainer dari gambar dasar NVIDIA FFmpeg dan menambahkan runtime Python.
FROM registry.cn-shanghai.aliyuncs.com/serverless_devs/nvidia-ffmpeg:latest WORKDIR /usr/src/app RUN apt-get update --fix-missing RUN apt-get install -y python3 RUN apt-get install -y python3-pip COPY . . ENTRYPOINT [ "python3", "-u", "/usr/src/app/app.py" ] EXPOSE 9000Bangun gambar kontainer.
s build --dockerfile ./code/DockerfileSebarkan ke Function Compute.
Jika Anda menjalankan
s deploylagi dengan nama layanan dan fungsi yang sama, jalankanuse localterlebih dahulu untuk menggunakan konfigurasi lokal.s deployBuat instans yang disediakan agar fungsi GPU siap menangani permintaan tanpa latensi cold start.
s provision put --target 1 --qualifier LATESTVerifikasi bahwa instans yang disediakan sudah siap.
s provision get --qualifier LATESTInstans siap digunakan ketika
currentsama dengan1. Contoh output:[2021-12-14 08:45:24] [INFO] [S-CLI] - Start ... [2021-12-14 08:45:24] [INFO] [FC] - Getting provision: tgpu_ffmpeg_service.LATEST/tgpu_ffmpeg_func customContainer-demo: serviceName: tgpu_ffmpeg_service functionName: tgpu_ffmpeg_func qualifier: LATEST resource: 188077086902****#tgpu_ffmpeg_service#LATEST#tgpu_ffmpeg_func target: 1 current: 1 scheduledActions: (empty array) targetTrackingPolicies: (empty array) currentError:Panggil fungsi tersebut. Periksa versi yang telah disebarkan:
s invokeTranskode dengan CPU:
s invoke -e '{"method":"GET","headers":{"TRANS-MODE":"cpu"}}'Transkode dengan GPU:
s invoke -e '{"method":"GET","headers":{"TRANS-MODE":"gpu"}}'Setelah selesai, lepas instans yang disediakan untuk menghentikan biaya.
s provision put --target 0 --qualifier LATEST
Sebarkan fungsi GPU dari konsol
Siapkan gambar kontainer.
Buat instans Container Registry Edisi Perusahaan (direkomendasikan) atau instans Edisi Personal. Lihat Buat instans Container Registry Edisi Perusahaan.
Buat namespace dan repository image di instans tersebut. Lihat Buat namespace dalam dokumentasi Container Registry. Lalu ikuti langkah-langkah untuk membuat repository image di instans yang sama.
Ikuti instruksi Docker di Konsol Container Registry untuk mendorong
app.pydanDockerfile(dari direktori/codeServerless Devs) ke repository image.

Buat layanan. Lihat bagian Buat layanan.
Buat fungsi. Lihat Buat fungsi kontainer kustom.
Atur Instance Type ke GPU Instance dan Request Handler Type ke Process HTTP Requests.
Tingkatkan periode timeout eksekusi. Transkoding CPU untuk video berdurasi 2 menit membutuhkan waktu lebih dari 100 detik — jauh di atas timeout default 60 detik.
Temukan fungsi tersebut dan klik Configure di kolom Actions.
Di bagian Environment Information, tingkatkan Execution Timeout Period lalu klik Save.

Konfigurasikan instans yang dipercepat GPU yang disediakan. Setelah pembuatan, periksa daftar aturan dan pastikan bahwa Current Reserved Instances sesuai dengan jumlah target Anda.
Di halaman detail fungsi, klik tab Auto Scaling, lalu klik Create Rule.
Konfigurasikan parameter untuk menyediakan instans yang dipercepat GPU lalu klik Create. Lihat Konfigurasikan aturan penskalaan otomatis untuk detailnya.

Uji fungsi dengan cURL.
Di halaman detail fungsi, klik tab Triggers untuk mendapatkan titik akhir pemicu.
Jalankan perintah berikut:
Periksa versi yang telah disebarkan:
curl -v "https://tgpu-ff-console-tgpu-ff-console-ajezot****.cn-shenzhen.fcapp.run" {"function": "trans_gpu"}Transkode dengan CPU:
curl "https://tgpu-ff-console-tgpu-ff-console-ajezot****.cn-shenzhen.fcapp.run" -H 'TRANS-MODE: cpu' {"result": "ok", "upload_time": 8.75510573387146, "download_time": 4.910430669784546, "trans_time": 105.37688875198364}Transkode dengan GPU:
curl "https://tgpu-ff-console-tgpu-ff-console-ajezotchpx.cn-shenzhen.fcapp.run" -H 'TRANS-MODE: gpu' {"result": "ok", "upload_time": 8.313958644866943, "download_time": 5.096682548522949, "trans_time": 8.72346019744873}
Hasil
Akses hasil transkoding dari browser Anda menggunakan nama domain OSS. Contohnya:
https://cri-zbtsehbrr8******-registry.oss-cn-shenzhen.aliyuncs.com/output.flvGanti nama domain dengan titik akhir OSS aktual Anda.
Langkah selanjutnya
Jenis instans dan mode instans — pelajari lebih lanjut tentang opsi instans yang dipercepat GPU
Konfigurasikan instans yang disediakan dan aturan penskalaan otomatis — optimalkan perilaku cold start untuk fungsi GPU