Bài viết gần đây
Trang chủ → Bài Viết → Vì Sao Render Kaleido Mất 1 Giây (Python) Nhưng 45 Giây (NodeJS)? Tối Ưu Plotly → Video
| Vì Sao Render Kaleido Mất 1 Giây (Python) Nhưng 45 Giây (NodeJS)? Tối Ưu Plotly → Video
Được viết bởi Đặng Trí Thanh vào ngày 23/08/2026 lúc 11:33 | 23 lượt xem
Khi xây dựng video dữ liệu bằng Plotly — đặc biệt là các video về AI, Data Analytics, Trading, Auto Trading và Financial Visualization — một vấn đề rất dễ gặp là tốc độ render từng frame.
Một ví dụ rất điển hình:
- Python chạy trên máy local thông qua VS Code: khoảng 1 giây/frame
- NodeJS chạy trong môi trường Harness DeepSeek: khoảng 45 giây/frame
Nhìn vào hai con số này, rất dễ đi đến kết luận:
“Python nhanh hơn NodeJS 45 lần.”
Nhưng kết luận này không chính xác.
Điều thú vị là NodeJS và Python trong trường hợp này không phải yếu tố duy nhất quyết định tốc độ. Phần lớn thời gian render còn phụ thuộc vào Kaleido, Chromium/rendering engine, CPU, RAM, container, filesystem, cách khởi tạo process và cách chương trình tạo từng frame.
Để hiểu chính xác chuyện gì đang xảy ra, trước tiên cần hiểu “frame” là gì.
1. Frame là gì?
Trong video, một frame là một hình ảnh tĩnh.
Một video thực chất không phải là một hình ảnh chuyển động duy nhất. Nó là một chuỗi rất nhiều hình ảnh được hiển thị liên tiếp với tốc độ đủ nhanh để mắt người cảm nhận thành chuyển động.
Ví dụ video 30 FPS.
FPS là viết tắt của Frames Per Second — tức là số frame được hiển thị trong một giây.
Nếu video chạy ở:
- 24 FPS → 24 frame/giây
- 30 FPS → 30 frame/giây
- 60 FPS → 60 frame/giây
Ví dụ một video dài 10 giây ở 30 FPS sẽ cần:
10 × 30 = 300 frame
Có thể hình dung:
Frame 001 → Frame 002 → Frame 003 → Frame 004 → ... → Frame 300
Mỗi frame chỉ là một hình ảnh. Khi những hình ảnh này được phát liên tục:
IMAGE → IMAGE → IMAGE → IMAGE → IMAGE
não người sẽ cảm nhận thành:
VIDEO
2. Vì sao Plotly animation có thể cần hàng trăm hoặc hàng nghìn frame?
Plotly rất mạnh trong việc tạo biểu đồ tương tác.
Ví dụ một biểu đồ giá:
BTCUSDT
Price
│
│ ╭───╮
│ ╭───╯ ╰──╮
│ ╭───╯ ╰──
└────────────────────── Time
Trong môi trường web, Plotly có thể sử dụng JavaScript để làm biểu đồ chuyển động ngay trên trình duyệt.
Nhưng nếu muốn biến biểu đồ này thành video MP4, câu chuyện khác hoàn toàn. Chúng ta cần tạo ra từng hình ảnh:
Frame 001 → giá tại thời điểm 1
Frame 002 → giá tại thời điểm 2
Frame 003 → giá tại thời điểm 3
...
Frame 300 → giá tại thời điểm 300
Sau đó mới ghép tất cả frame thành video.
3. Kaleido đóng vai trò gì?
Plotly có thể tạo chart. Nhưng để xuất chart thành hình ảnh như PNG, JPEG, SVG, PDF cần một rendering engine.
Kaleido là công cụ dùng để xuất Plotly figure thành hình ảnh hoặc các định dạng đầu ra tương ứng.
Có thể hình dung pipeline đơn giản:
Python / NodeJS
│
▼
Plotly
│
▼
Kaleido
│
▼
Rendering Engine
│
▼
PNG
Nếu tạo video:
Plotly
↓
Kaleido
↓
Frame 001 / 002 / 003 / ... / 300
↓
FFmpeg
↓
MP4
Điểm quan trọng là: Kaleido không phải toàn bộ hệ thống render. Tốc độ cuối cùng phụ thuộc vào cả pipeline.

4. Ví dụ thực tế: video 10 giây
Giả sử chúng ta muốn tạo video:
- Thời lượng: 10 giây
- FPS: 30
- Độ phân giải: 1920 × 1080
Số frame: 10 × 30 = 300 frame
Máy A – Python + VS Code
1 frame ≈ 1 giây
300 × 1 = 300 giây = 5 phút
Máy B – NodeJS + Harness
1 frame ≈ 45 giây
300 × 45 = 13.500 giây ≈ 225 phút ≈ 3 giờ 45 phút
Đây là khác biệt cực kỳ lớn.
5. Có phải Python nhanh hơn NodeJS 45 lần?
Không nên kết luận như vậy. Đây là sai lầm phổ biến nhất.
Nếu thực hiện một phép tính CPU đơn giản:
for i in range(1000000):
x = i * i
rồi so sánh Python với NodeJS, chúng ta mới đang so sánh một phần hiệu năng của hai runtime.
Nhưng render Plotly bằng Kaleido là một bài toán hoàn toàn khác. Pipeline thực tế có thể giống:
NodeJS
↓
Plotly
↓
Kaleido
↓
Chromium
↓
Rendering
↓
Filesystem
↓
PNG
Do đó:
45 giây/frame không đồng nghĩa NodeJS chậm hơn Python 45 lần.
Nó có thể đơn giản là:
NodeJS đang chạy Kaleido trong một môi trường kém thuận lợi hơn rất nhiều.
6. Yếu tố đầu tiên: môi trường chạy
Đây có thể là nguyên nhân lớn nhất.
Python của bạn đang chạy:
VS Code → Máy local → CPU thật → RAM thật → SSD local → Kaleido
Trong khi NodeJS trên Harness DeepSeek có thể chạy trong:
Harness → Container / Sandbox → CPU được phân bổ → RAM giới hạn
→ Filesystem của môi trường → Kaleido
Hai môi trường này không tương đương. Đây là điểm cần kiểm tra đầu tiên.
7. Container có thể làm render chậm như thế nào?
Container rất hữu ích cho việc triển khai ứng dụng. Nhưng môi trường container không phải lúc nào cũng có hiệu năng giống máy vật lý.
Có thể có:
- CPU quota
- CPU throttling
- giới hạn RAM
- I/O chậm
- filesystem layer
- process isolation
- startup overhead
- network filesystem
- sandbox restrictions
Đặc biệt nếu rendering engine phải khởi tạo nhiều process, những overhead này có thể trở nên rất rõ ràng.
Ví dụ:
Local: CPU ████████████████████ ████████████████████
Harness: CPU ███ ███ ███
Nếu container chỉ được cấp một phần CPU, rendering sẽ chậm.
8. Yếu tố thứ hai: Chromium/rendering engine
Đây là một điểm rất quan trọng.
Kaleido không chỉ đơn giản là Python → PNG. Quá trình render có thể liên quan đến một rendering engine để biến figure Plotly thành hình ảnh.
Điều này có nghĩa là: CPU và môi trường chạy rendering engine rất quan trọng.
Nếu rendering engine chạy trên:
- CPU mạnh
- RAM đủ
- local SSD
thì tốc độ có thể rất tốt.
Nếu chạy trong:
- container giới hạn CPU
- RAM thấp
- sandbox
- filesystem chậm
thì tốc độ có thể giảm mạnh.
9. Yếu tố thứ ba: khởi tạo Kaleido nhiều lần
Đây là một lỗi kiến trúc rất đáng kiểm tra.
Giả sử chúng ta cần render 300 frame.
Cách tốt:
Start Kaleido
↓
Frame 1 → Frame 2 → Frame 3 → ... → Frame 300
↓
Close
Nhưng nếu code làm:
Start Kaleido → Frame 1 → Close
Start Kaleido → Frame 2 → Close
Start Kaleido → Frame 3 → Close
thì sẽ rất tốn thời gian. Mỗi frame có thể phải chịu:
Process startup + Rendering startup + Chart creation + Rendering + File write + Process shutdown
Nếu lặp hàng trăm lần, overhead trở thành cực lớn.
10. Vì sao vấn đề này đặc biệt nghiêm trọng với video?
Một chart đơn lẻ có thể không đáng kể:
1 chart = 1 giây → nghe có vẻ ổn
Nhưng video 1 phút ở 30 FPS: 60 × 30 = 1.800 frame
Nếu 1 frame = 1 giây: 1.800 giây = 30 phút
Nếu 1 frame = 45 giây: 1.800 × 45 = 81.000 giây ≈ 22,5 giờ
Như vậy một video 1 phút có thể mất gần một ngày chỉ để render frame. Đây là lý do phải tối ưu pipeline ngay từ đầu.
11. Yếu tố thứ tư: chart quá nặng
Không phải tất cả frame đều giống nhau về độ phức tạp.
Một chart đơn giản:
1 line · 100 points
rất nhẹ.
Nhưng một chart trading cao cấp có thể chứa:
Candlestick + Volume + MA50 + MA200 + RSI + MACD
+ Buy Signal + Sell Signal + Annotations + Shapes + Text + Background + Glow
Khi đó mỗi frame phải render rất nhiều đối tượng:
Frame
├── Candlestick
├── Volume
├── MA
├── RSI
├── MACD
├── Signals
├── Text
├── Shapes
├── Annotations
└── Background
Nếu mỗi frame thay đổi dữ liệu và toàn bộ figure được tạo lại, rendering có thể rất tốn CPU.

12. Yếu tố thứ năm: độ phân giải
1920 × 1080 có 2.073.600 pixels. Mỗi frame phải render hơn 2 triệu pixel.
Nếu video 300 frame: 2.073.600 × 300 đã là một lượng pixel khổng lồ cần xử lý.
Nếu nâng lên 4K (3840 × 2160) thì số pixel tăng lên khoảng 4 lần so với Full HD.
Do đó:
720p → 1080p → 1440p → 4K
thời gian render có thể tăng đáng kể.
13. Yếu tố thứ sáu: file I/O
Sau khi render xong frame, chương trình phải ghi file:
frame_0001.png
frame_0002.png
frame_0003.png
...
frame_0300.png
Nếu filesystem nhanh (SSD) thì Render → SSD → Fast.
Nếu filesystem chậm (container) thì:
Render → Container filesystem → Write → Sync → Slow
thì mỗi frame lại mất thêm thời gian.
Nếu một frame mất 45 giây, cần xác định:
45 giây đó thực sự dùng cho rendering hay đang bị mất ở I/O?
14. Cách benchmark đúng
Đừng chỉ đo total_time / number_of_frames. Hãy đo từng thành phần:
Create Figure → Render → Write PNG → Next Frame
Ví dụ:
Figure creation: 0.2s
Kaleido render: 0.7s
File write: 0.1s
Total: 1.0s
Nếu trên Harness:
Figure creation: 1s
Kaleido render: 40s
File write: 4s
Total: 45s
thì biết ngay bottleneck nằm ở đâu.
15. Bài test quan trọng nhất
Muốn xác định chính xác nguyên nhân, hãy tạo một chart cực kỳ đơn giản:
100 points · 1 line · không candlestick · không annotation · không image · không nhiều trace
Sau đó render 10 frame và đo:
Python local
NodeJS Harness
Nếu kết quả:
Python = 1s/frame
NodeJS = 45s/frame
thì gần như chắc chắn vấn đề nằm ở:
- environment
- Kaleido setup
- Chromium
- process startup
- CPU
- filesystem
Không phải do chart.
16. Nếu chart đơn giản chỉ mất 1–2 giây thì sao?
Ví dụ kết quả:
Python: 1.0s
NodeJS: 1.5s
nhưng chart thật:
Python: 1s
NodeJS: 45s
thì vấn đề nằm ở cách xây dựng chart. Khi đó cần kiểm tra:
- số lượng trace
- số lượng point
- annotations
- shapes
- images
- text
- candlestick
- animation
- figure size
- layout
- data processing
17. Python và NodeJS nên phân vai thế nào?
Nếu hệ thống của bạn đang phát triển theo hướng Website → NodeJS → AI → Data → Video thì không nhất thiết phải ép NodeJS làm toàn bộ.
Một kiến trúc rất hợp lý:
USER → WEBSITE → NodeJS → Database / Job → Python Worker
↓
Plotly → Kaleido → PNG → FFmpeg → MP4
NodeJS chịu trách nhiệm:
- API
- authentication
- database
- job management
- user interface
- nhận request
- quản lý trạng thái render
Python chịu trách nhiệm:
- Pandas
- NumPy
- Plotly
- Data processing
- Kaleido
- chart rendering
FFmpeg chịu trách nhiệm:
- ghép frame
- encode MP4
- audio
- bitrate
- codec
Đây là mô hình rất phù hợp cho hệ thống Data/Trading/AI Video.

18. Tại sao không nhất thiết phải dùng NodeJS cho Plotly?
Nếu phần mạnh nhất của hệ thống hiện tại là Python + Data Science thì không nên bỏ lợi thế đó chỉ vì backend chính dùng NodeJS.
Python có hệ sinh thái rất mạnh:
Pandas · NumPy · Plotly · Scikit-learn · Matplotlib · OpenCV · Pillow
Trong khi NodeJS rất mạnh ở:
API · WebSocket · REST · Realtime · Backend · Queue · Microservices
Hai bên có thể phối hợp. Không cần lựa chọn Python hoặc NodeJS — có thể lựa chọn Python + NodeJS.
19. Một kiến trúc nâng cao hơn: Job Queue
Nếu người dùng bấm “Generate Video”, NodeJS không nên giữ request quá lâu.
Thay vào đó:
User → NodeJS → Create Render Job → Queue → Python Worker → Render → MP4
→ Storage → NodeJS cập nhật trạng thái → User nhận video
Trạng thái có thể là:
QUEUED → PROCESSING → RENDERING → ENCODING → COMPLETED
Website có thể hiển thị:
Rendering video...
Frame: 174 / 300
58%
ETA: 02:14
Đây sẽ tạo thành một hệ thống chuyên nghiệp hơn rất nhiều.
20. Có cần render tất cả frame bằng Kaleido không?
Đây cũng là câu hỏi quan trọng. Không phải mọi animation đều nhất thiết phải được render bằng cách tạo toàn bộ figure mới cho từng frame.
Có thể tối ưu bằng cách:
- giảm số frame
- giảm dữ liệu
- tái sử dụng figure
- giảm số trace
- giảm annotation
- giảm độ phân giải trong preview
- dùng animation native khi phù hợp
- render final ở độ phân giải cao
- sử dụng FFmpeg cho các hiệu ứng hậu kỳ
Ví dụ, thay vì 300 frame × chart cực nặng, có thể thiết kế Plotly animation + motion graphics + FFmpeg để đạt hiệu ứng tốt hơn với ít chi phí render hơn.
21. Không phải hiệu ứng nào cũng cần Plotly
Plotly nên phụ trách:
DATA · CHART · TRADING · STATISTICS · ANALYTICS
Còn các hiệu ứng:
FLASH · GLOW · ZOOM · GLITCH · TEXT · TRANSITION · PARTICLE · LIGHT
có thể xử lý bằng motion graphics hoặc FFmpeg/Python/OpenCV tùy pipeline.
Ví dụ:
Plotly → Chart
Python/OpenCV → Motion
FFmpeg → Final composition
22. Tối ưu video YouTube như thế nào?
Một video YouTube không nhất thiết phải render mọi thứ ở 60 FPS. Nếu nội dung chủ yếu là chart, dashboard, data, text, trading thì 30 FPS thường đã đủ mượt.
60 FPS — video 30 giây
30 × 60 = 1.800 frame
30 FPS
30 × 30 = 900 frame
Giảm từ 60 xuống 30 FPS đồng nghĩa giảm một nửa số frame.
Nếu mỗi frame mất 1 giây:
60 FPS → 1.800 giây
30 FPS → 900 giây
Đây là một tối ưu cực kỳ đơn giản nhưng hiệu quả.
23. Preview và Final Render phải khác nhau
Một workflow chuyên nghiệp không nên render thử ở 4K ngay từ đầu.
Preview: 1280 × 720 · 15 FPS — mục tiêu kiểm tra animation.
Sau khi duyệt:
Final: 1920 × 1080 · 30 FPS — mục tiêu xuất bản YouTube/Website.
Nếu cần:
Master: 3840 × 2160 · 30 FPS — mục tiêu lưu bản chất lượng cao.
24. Một phép tính để thấy vấn đề
Giả sử: 30 giây · 30 FPS → cần 900 frame.
- Nếu 1 giây/frame:
900 giây = 15 phút - Nếu 5 giây/frame:
4.500 giây = 75 phút - Nếu 45 giây/frame:
40.500 giây ≈ 11 giờ 15 phút
Chỉ cần từ 1 giây tăng lên 45 giây/frame là pipeline gần như không thể sử dụng để sản xuất video hàng loạt.
25. Vì vậy 45 giây/frame cần được điều tra
Đây không phải mức tốc độ nên chấp nhận ngay.
Trước khi tối ưu chart, cần kiểm tra:
CPU · RAM · CPU quota · Kaleido version · Chromium · NodeJS version
· Python version · Filesystem · Process startup · Chart complexity
· Number of traces · Number of points · PNG encoding
Đặc biệt:
Không nên kết luận “NodeJS chậm” trước khi benchmark cùng một chart trên cùng điều kiện phần cứng.
26. Benchmark công bằng nhất
Một benchmark tốt cần giữ nguyên:
Data · Figure · Width · Height · Format · Number of frames
Chỉ thay:
Environment
Ví dụ:
Test Chart: 100 points · 1 line · 1920×1080 · PNG · 10 frames
Python Local: 10 frames = 10s
NodeJS Local: 10 frames = 12s
NodeJS Harness: 10 frames = 450s
Khi đó có thể kết luận:
Vấn đề chủ yếu nằm ở Harness environment.
27. Còn nếu NodeJS local cũng nhanh?
Nếu:
Python local ≈ 1s
NodeJS local ≈ 1s
NodeJS Harness ≈ 45s
thì câu trả lời gần như rõ ràng: NodeJS không phải bottleneck. Harness environment mới là vấn đề.
Khi đó có thể chuyển rendering về:
VPS · Dedicated server · Workstation · GPU/CPU server · Python worker
và NodeJS chỉ làm orchestration.
28. Một hệ thống hoàn chỉnh cho AI/Data Video
WEBSITE → NodeJS API → Render Queue
↓
Python Worker 1 / Python Worker 2
↓
Plotly → Kaleido → PNG Frames
↓
FFmpeg → MP4 → Storage
↓
Website → YouTube
Khi có nhiều người dùng, có thể chạy nhiều worker song song:
Worker 1 → Video A
Worker 2 → Video B
Worker 3 → Video C
Worker 4 → Video D
Thay vì một process xử lý tuần tự toàn bộ.
29. Từ video Plotly đến hệ thống sản xuất nội dung
Hệ thống này không chỉ dùng cho một video — bạn có thể biến nó thành một Data Video Engine.
Ví dụ user nhập:
Symbol: XAUUSD
Timeframe: M15
Period: 30 days
Style: Futuristic
NodeJS nhận request, sau đó Python:
Fetch Data → Calculate Indicators → Generate Plotly → Generate Animation
→ Render Frames → FFmpeg → MP4
Kết quả: XAUUSD_M15_AI_ANALYSIS.mp4
Sau đó hệ thống có thể tự tạo:
- Video YouTube
- YouTube Shorts
- TikTok
- Facebook Reels
- Website article
- Thumbnail
- Description
- SEO keywords
Đây chính là hướng có thể phát triển thành một AI Content Automation Platform.
30. Kết luận
Câu hỏi “Tại sao Python mất 1 giây/frame nhưng NodeJS mất 45 giây/frame?” không nên được trả lời đơn giản là “Python nhanh hơn NodeJS.”
Câu trả lời chính xác hơn là:
Tốc độ render Plotly/Kaleido phụ thuộc vào toàn bộ môi trường và pipeline rendering, không chỉ phụ thuộc vào ngôn ngữ lập trình.
Trong trường hợp Python + VS Code ≈ 1s/frame và NodeJS + Harness ≈ 45s/frame, cần đặc biệt kiểm tra:
- CPU được cấp cho Harness.
- RAM.
- Container/sandbox.
- Chromium/rendering engine.
- Cách khởi tạo Kaleido.
- Có khởi tạo process lại ở mỗi frame hay không.
- Filesystem.
- Độ phức tạp của Plotly chart.
- Số lượng trace.
- Số lượng data point.
- Độ phân giải.
- PNG encoding.
- Cách tạo animation.
Điều quan trọng nhất là:
45 giây/frame là một dấu hiệu cần điều tra, không phải một đặc tính bình thường của NodeJS.
Nếu benchmark chứng minh NodeJS local cũng nhanh nhưng Harness rất chậm, hãy giữ NodeJS làm Backend/Orchestrator và đưa phần Plotly + Kaleido sang Python Worker.
Kiến trúc lý tưởng:
NodeJS → API / Queue / Job → Python Worker → Plotly → Kaleido
→ PNG Frames → FFmpeg → MP4
Với cách này, bạn vừa giữ được ưu thế của NodeJS cho hệ thống Web/API, vừa tận dụng được hệ sinh thái Python cho Data + Plotly + Visualization, đồng thời có thể mở rộng thành hệ thống tự động sản xuất video cho AI, Data Analytics, Trading và Auto Trading.
Tóm tắt ngắn
1 frame = 1 hình ảnh
30 FPS = 30 hình/giây
10 giây video = 300 frame
Python ≈ 1s/frame → 300 frame ≈ 5 phút
NodeJS Harness ≈ 45s/frame → 300 frame ≈ 3 giờ 45 phút
Không nên vội kết luận Python nhanh hơn NodeJS 45 lần. Hãy kiểm tra môi trường render trước.
Nếu mục tiêu là xây dựng hệ thống lâu dài, NodeJS + Python Worker + Plotly + Kaleido + FFmpeg là kiến trúc phù hợp nhất cho bài toán này.
Muốn tự tay xây dựng pipeline Data Video & Bot?
Khóa Lập trình Python Cơ bản — từ xử lý dữ liệu đến Plotly/Kaleido render video cho AI & Trading.
Weekly Digest — Nhận Bản Tin Hàng Tuần
Nhận các bài viết phân tích kỹ thuật chuyên sâu, thuật toán giao dịch tự động (Trading Bot) và các giải pháp công nghệ mới nhất từ Hướng Nghiệp Dữ Liệu.
Đặng Trí Thanh
Giám đốc Công nghệ · DNT Digital · Giảng viên HNDLĐặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu - DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.