← Tất cả bài viết

[ Blog ]

9 tháng 7, 2026

9 phút đọc

Lỗi ffmpeg "Operation Not Permitted" trên macOS: Cách Sửa

Gặp lỗi "Operation not permitted" khi chạy ffmpeg trên file trong Downloads macOS? Không phải lỗi cài đặt — đó là TCC chặn app terminal. Đây là cách sửa thật.

macOSffmpegPermissionsCLITCCDevTools
Lỗi ffmpeg "Operation Not Permitted" trên macOS: Cách Sửa

Tôi kéo một file video vào ~/Downloads, chạy một lệnh ffmpeg đơn giản trên nó từ terminal, và nhận được một tràng Operation not permitted. Không phải lỗi codec, không thiếu dependency — mà là một cú từ chối quyền thẳng thừng, trên một file tôi vẫn thấy nằm rành rành trong Finder. Nếu bạn gặp lỗi "operation not permitted" khi chạy ffmpeg trên file trong thư mục Downloads trên macOS, thủ phạm không phải ffmpeg, cũng không phải shell của bạn. Đó là chính macOS đang âm thầm chặn cái app chứa terminal của bạn. Đây là cách tôi truy ra nguyên nhân và hai cách sửa thật sự.

Triệu chứng: ls chạy được, ffmpeg thì không

Điều đầu tiên khiến bug này khó hiểu là nó không nhất quán — một số lệnh chạy bình thường, số khác fail thẳng trên đúng cùng một file:

$ ls -la ~/Downloads/clip.mov
-rw-r--r--@ 1 hon  staff  48213991 Jul  9 10:02 clip.mov

$ ffmpeg -i ~/Downloads/clip.mov -c:v libx264 -crf 20 out.mp4
[in#0 @ 0x14b006a80] Error opening input: Operation not permitted
Error opening input file ~/Downloads/clip.mov.
Error opening input files: Operation not permitted

ls đọc metadata của thư mục — phần này được cache và gần như không bị chặn. ffmpeg thì cần mở file để đọc nội dung thật sự, và đó chính là thao tác macOS chặn lại. cat thuần cũng gặp y hệt:

$ cat ~/Downloads/clip.mov > /dev/null
cat: /Users/hon/Downloads/clip.mov: Operation not permitted

cp cũng vậy. Đến đây rất dễ đổ lỗi cho bản build ffmpeg, một bản cài Homebrew bị lỗi, hay cờ sandbox nào đó trong terminal (hoặc AI coding agent) đang chạy lệnh. Tôi mất hai mươi phút đi theo hướng đó trước khi kiểm tra đúng thứ giải thích tất cả: macOS TCC.

Đây là TCC, không phải sandbox của công cụ

TCC (Transparency, Consent, and Control) là lớp bảo mật quyền riêng tư của macOS, quản lý những app nào được chạm vào dữ liệu người dùng nhạy cảm — camera, micro, danh bạ, và kể từ Catalina, một nhóm thư mục được bảo vệ: ~/Downloads, ~/Desktop, ~/Documents, cộng thêm mọi thứ nằm trong iCloud Drive. Lớp bảo vệ này không tính theo từng process hay từng công cụ CLI — nó được cấp cho application bundle đã sinh ra process đó. Tài liệu chính thức của Apple về cơ chế này ở đây: TCC và bảo vệ quyền riêng tư cho app, còn tài liệu dành cho developer nằm ở App Sandbox và privacy.

Điều tôi hiểu sai lúc đầu: tôi nghĩ đây là chuyện của bản thân công cụ CLI — một entitlement sandbox nào đó trên ffmpeg, hoặc giới hạn trong shell của một AI coding agent. Không phải cả hai. Khi một process đọc file trong thư mục được TCC bảo vệ, macOS lần ngược lên chuỗi process cha để tìm ứng dụng GUI thật sự chịu trách nhiệm — terminal, editor, bất cứ thứ gì đã sinh ra shell — rồi kiểm tra quyền Full Disk Access của app đó. Nếu đó là một bản fork VS Code như Cursor, hay bất kỳ app terminal nào chưa được cấp quyền, lệnh đọc bị từ chối, bất kể công cụ đang yêu cầu vô hại đến đâu. Tắt cờ sandbox của CLI, cài lại ffmpeg, hay đổi shell đều không thay đổi gì, vì không cái nào là thứ macOS đang kiểm tra.

Tìm ra app mà TCC đang thật sự chặn

Trước khi cấp quyền cho bất cứ thứ gì, hãy xác nhận app nào đang bị "để ý". Hai cách kiểm tra nhanh ngay từ shell đang bị lỗi:

$ echo $__CFBundleIdentifier
com.todesktop.230313mzl4w4u92   # Cursor, trong trường hợp của tôi — một bản fork VS Code

Nếu biến này rỗng hoặc không rõ ràng, hãy lần theo chuỗi process cha — cách này hoạt động với bất kỳ shell nào, dù có agent điều khiển hay không:

$ ps -o pid,ppid,comm -p $$
  PID  PPID COMM
12345  6789 /bin/zsh

$ ps -o pid,ppid,comm -p 6789
  PID  PPID COMM
 6789     1 /Applications/Cursor.app/Contents/MacOS/Cursor

.app xuất hiện ở đầu chuỗi đó chính là thứ cần được cấp Full Disk Access — không phải shell, không phải ffmpeg, không phải AI coding agent đang điều khiển nó. Trường hợp AI coding agent không đọc được file trong Downloads gần như luôn là đúng chuỗi này: agent chạy một shell, shell thừa hưởng danh tính TCC của app chủ, và app chủ đó chưa từng được cấp quyền.

Cách sửa 1: cấp Full Disk Access, rồi thoát hẳn app

Đây là cách sửa lâu dài nếu bạn sẽ còn làm việc thường xuyên với ~/Downloads, ~/Desktop, hoặc ~/Documents:

  1. System Settings → Privacy & Security → Full Disk Access.
  2. Bấm + và thêm app chủ bạn vừa xác định ở trên (Cursor, VS Code, Terminal, iTerm2 — bất cứ app nào đang sở hữu chuỗi process).
  3. Bật công tắc lên.
  4. Thoát hẳn app⌘Q, không chỉ đóng cửa sổ — rồi mở lại.

Bước 4 là phần mọi người hay bỏ qua rồi báo rằng cách sửa "không có tác dụng". Quyền TCC được đánh giá tại thời điểm process của app khởi động; một process đang chạy vẫn giữ trạng thái cũ (bị từ chối) cho đến khi khởi động lại. Chạy lại đúng lệnh ffmpeg trong cùng cửa sổ terminal vẫn đang mở ngay sau khi bật công tắc, bạn sẽ vẫn gặp đúng lỗi Operation not permitted. Hãy thoát, mở lại, rồi thử lại.

Đây cũng là lý do tắt cài đặt sandbox bên trong công cụ chẳng bao giờ giúp ích: việc kiểm tra diễn ra ở lớp cao hơn, cấp hệ điều hành, dựa trên danh tính app bundle — không phải quyền riêng của ffmpeg.

Cách sửa 2: chuyển file vào project thay vì cấp quyền

Nếu bạn không muốn đụng vào quyền hệ thống — hoặc đang chạy lệnh này từ shell của một AI coding agent và không muốn cấp Full Disk Access toàn phần cho một app chủ — có một cách nhanh hơn, không cần khởi động lại app nào cả:

# Copy qua Finder, không phải cp trong terminal:
# kéo clip.mov từ ~/Downloads vào thư mục project, ví dụ ./assets/
$ ffmpeg -i ./assets/clip.mov -c:v libx264 -crf 20 out.mp4
# chạy được ngay

Điểm mấu chốt là cách file được di chuyển. Kéo thả trong Finder dùng quyền TCC riêng của Finder (Finder luôn có quyền truy cập các thư mục người dùng), nên bản copy nằm trong project không còn nằm trong đường dẫn được bảo vệ — thư mục repo của bạn chưa bao giờ là một trong các thư mục TCC canh giữ. Chạy cp từ cùng terminal đang bị chặn thì không giúp gì, vì lệnh cp đó vẫn thừa hưởng đúng danh tính bị từ chối như ffmpeg. Bắt buộc phải là thao tác kéo hoặc copy từ phía Finder.

Đây chính là cách tôi đã dùng vào ngày gặp lỗi này: tôi đang giữa lúc encode một video hero scrub theo scroll và không muốn dừng lại để cấp quyền rồi khởi động lại editor giữa chừng. Kéo file gốc vào thư mục assets/ của project giải quyết được lệnh encode chỉ trong khoảng năm giây.

Nên dùng cách sửa nào?

Tình huốngNên dùng
Bạn sẽ tiếp tục làm việc thường xuyên với ~/Downloads/~/DesktopFull Disk Access (cách 1) — cài một lần
Bạn chỉ cần gỡ chặn cho đúng file này, ngay bây giờKéo vào project (cách 2) — không cần khởi động lại
Bạn đang chạy lệnh từ shell của một AI coding agentƯu tiên cách 2 (không phải ngắt mạch làm việc); dùng cách 1 nếu lặp lại thường xuyên
CI hoặc script chạy ngầm gặp đúng lỗi nàyKhông áp dụng — TCC là cài đặt theo từng user, gắn với app GUI, không áp dụng theo cách tương tự cho CI chạy không tương tác; hãy kiểm tra quyền sở hữu file trên runner của bạn thay vì tìm TCC

FAQ

Vì sao ls chạy được nhưng cat hay ffmpeg báo permission denied trên Mac?

ls đọc metadata thư mục đã được cache, thứ macOS không chặn qua TCC. Mở nội dung thật sự của file — điều mà cat, cp, và ffmpeg đều cần làm — mới kích hoạt kiểm tra TCC trên app cha. Đó chính là nguồn gốc của sự khó hiểu này.

Tôi đã mở Cursor/một app terminal — vì sao Full Disk Access vẫn báo "permission denied"?

Vì quyền TCC được áp dụng tại thời điểm process khởi động, không phải ngay lập tức. App đã chạy sẵn trước khi bạn cấp quyền vẫn đang vận hành với trạng thái cũ (bị từ chối). Hãy thoát hẳn bằng ⌘Q rồi mở lại — đóng cửa sổ hay mở tab mới là chưa đủ, toàn bộ process phải khởi động lại.

AI coding agent có đọc được file trong Downloads nếu tôi tắt sandbox của nó không?

Không. Đây chính là sai lầm đầu tiên của tôi. Các công cụ shell của agent không phải thứ TCC đang kiểm tra — nó kiểm tra ứng dụng GUI đã sinh ra shell đó (editor hoặc terminal). Tắt sandbox ở cấp công cụ không có tác dụng gì với một hệ thống quyền cấp hệ điều hành, dựa trên danh tính app.

Lỗi này chỉ ảnh hưởng Downloads, hay cả những thư mục khác?

Bảo vệ "Files and Folders" của TCC mặc định bao phủ ~/Downloads, ~/Desktop, ~/Documents, và iCloud Drive, cộng thêm bất cứ thứ gì bạn đã tự bảo vệ thêm. Một thư mục project bạn tự tạo, ví dụ dưới ~/dev, chỉ bị bảo vệ nếu nó nằm bên trong một trong các thư mục gốc đó — di chuyển file làm việc ra ngoài các thư mục này thì việc kiểm tra sẽ không áp dụng nữa.

Có cách nào dùng command line để kiểm tra hoặc reset quyền TCC không?

Apple không cung cấp một CLI được hỗ trợ đầy đủ để truy vấn quyền TCC theo từng app — System Settings là con đường chính thức. Nếu một quyền có vẻ bị kẹt hoặc sai, xóa app khỏi danh sách Full Disk Access rồi thêm lại (kèm thoát hẳn/mở lại) sẽ reset trạng thái sạch sẽ.


Nếu bạn đang xử lý media qua ffmpeg như một phần của pipeline lớn hơn — tôi đã gặp đúng bức tường này khi encode một video hero scrub theo scroll cho một trang web điều khiển bằng scroll — đáng để biết trước cái bẫy này tồn tại trước khi nó ngốn hai mươi phút buổi chiều của bạn. Và nếu bạn muốn giao hẳn cả pipeline animation/video cho người đã từng gỡ lỗi những thứ này rồi, xem cách tôi làm việc với các đội nhóm.