做视频数据集最大的痛点从来不是算法选型而是标注。尤其是视频目标检测任务动辄几千帧画面一帧一帧画框能把人逼疯。我在2020年初接到一个内部项目需要快速攒一批标注数据专门去调研了一圈视频标注工具最终锁定MIT开源的VATIC视频标注工具。它最大的特点是把人工标注和自动跟踪结合起来标注员只需要在关键帧上画框后台算法会帮忙把框延续到相邻帧效率比纯手工高出一大截。不过调研的时候发现一个很现实的问题全网铺天盖地的教程都是基于Docker一键部署的偏偏我们团队那台标注服务器出于统一管理考虑没有预装Docker环境加上很多业务服务已经在裸机上跑着实在不想为这一个工具打乱虚拟化规划。于是只能硬着头皮走非docker路线自己手动把Apache、MySQL、PHP、Python和ffmpeg这一串依赖全部搭起来。这篇文章就是那次完整安装过程的记录包括我踩过的坑以及一些网上教程基本不会提的细节。如果你也在纠结要不要跳过docker手动装VATIC或者已经装到一半卡住了可以参考一下。1. 为什么明明有docker版我还要手动装1.1 VATIC到底解决什么问题先说清楚VATIC是干什么的免得有人白折腾一趟。VATIC的全称是Video Annotation Tool from Irvine, California一个用于视频目标标注的开源系统。它的核心解决思路是把对一段视频的目标标注从“逐帧画框”变成“关键帧画框自动跟踪”。标注员打开网页在某一帧画面里拖出一个目标框标注这个目标是什么类别后台会调用跟踪算法自动把框扩散到前后几十帧里。标注员只需要在跟踪丢失或偏离的地方手动修正然后确认就能很快完成一个视频片段。这套思路放在目标检测、行为识别、视频跟踪这类数据集的产线上非常实用。我手头这个项目需要一批“行人穿越路口”的视频片段如果用普通标注工具一帧一帧抠两个人干一周都未必能交付用VATIC的半自动模式时间能压缩到三分之一左右。这也是它十几年下来依然被人翻出来用、甚至还有人专门写非docker部署教程的根本原因。你要理解的是它本质上不是一个单纯的前端画框工具而是一套“前端交互后端跟踪计算”的完整系统。前端是PHP页面负责把视频帧渲染在浏览器里接收鼠标拖拽后端是Python脚本负责抽帧、跑跟踪算法、把结果写回数据库MySQL在中间存所有标注数据ffmpeg负责把视频拆成可标注的帧图片。这些角色缺一个都跑不起来。想清楚这条链路之后非docker安装要做什么就一目了然了。1.2 官方docker方案适合什么场景MIT官方确实提供了一个Dockerfile一条docker build加一条docker run就能把整个VATIC环境拉起来。如果你只是在一台有空闲Docker资源的机器上做短时间验证或者想快速看一下界面长什么样Docker方案非常省事镜像里已经把系统依赖和配置都封装好了不用关心底层装了哪个版本的PHP、MySQL。但我那次没有选Docker原因有三。第一服务器上已经跑着内部业务服务当时的环境里并没有预装Docker单独为了一个标注工具去申请虚拟化资源流程上要绕一大圈。第二VATIC上游镜像停更多年了基镜像里的系统库版本偏老和当时的漏洞扫描基线对不上安全同事那边就过不去。第三也是最重要的一点我们要在导出标注结果时对接自研的训练数据格式直接改VATIC代码比包在容器里改、再重新打镜像要直观得多。非docker安装的直接代价是所有依赖细节都摊在你面前每个环节都可能出问题。但好处也很实际你清楚地知道每一步装了什么、为什么装它后期要扩展、要修bug时不用隔着一层容器猜来猜去。2. 安装前需要理清的组件关系2.1 系统环境怎么选我这次安装在Ubuntu 16.04上完成。为什么选这个版本不是因为我恋旧而是VATIC的Python脚本和系统调用风格整体停留在Python 2时代。Ubuntu 16.04默认系统里Python 2和Python 3并存安装Python 2的依赖包很顺手PHP版本也还比较接近VATIC开发时期的5.x/7.0。如果你用的是Ubuntu 18.04之后的新系统系统默认Python已经切到3.x旧脚本很可能直接报语法错误这时要么给代码打补丁要么手动装一套Python 2.7环境工作量会大不少。选Ubuntu 16.04还有一个隐藏好处它的软件源里还保留着python-opencv这个带Python 2绑定的包。到了18.04之后这个包基本没了装OpenCV的兼容性麻烦事更多。2.2 五大组件怎么协作前面说过VATIC要靠五个组件一起工作Apache、MySQL、PHP、Python、ffmpeg。动工之前一定要把它们的协作关系理顺。浏览器打开Apache提供的页面时PHP代码会先请求MySQL读取当前标注任务对应的视频帧信息以及已有的目标框记录然后把帧图片渲染成页面里的画布。标注员在画布上拖出矩形框PHP再把这个框的坐标和类别信息写回MySQL。Python脚本不参与这种实时交互它的工作集中在任务准备和数据导出阶段把上传的视频用ffmpeg抽帧在抽取的帧序列上跑跟踪算法或者把数据库里的标注结果导出成训练集格式。Apache是调度入口PHP负责交互Python负责计算MySQL是中间仓库ffmpeg是视频处理管线缺一不可。2.3 版本兼容的坑要提前踩我吃过最大的亏是OpenCV版本兼容。VATIC后台脚本部分依赖OpenCV的旧接口其中有些调用已经到了cv2.cv这个命名空间OpenCV 3之后这个模块被移除了直接ImportError。如果我一开始就装系统默认的新版OpenCV连抽帧脚本都启动不了。所以安装之前我特意确认了一遍源里python-opencv对应的版本号确保和代码的接口使用匹配不符合就手动降级到兼容版本。2.4 视频数据要提前规范化安装软件之前还有一件容易被忽略的事准备视频数据。VATIC本身不负责视频转码它默认你提供的视频可以被ffmpeg正常解码。如果你手里的素材是H.265编码、4K分辨率或者特殊封装格式抽帧阶段会遇到很多莫名其妙的问题。我建议提前把待标注视频统一转成H.264AAC编码的MP4帧率也不要太激进控制在25fps或30fps这样抽帧稳定标注时帧跳转也不会卡。3. 逐项安装依赖3.1 安装基础编译工具和软件包一切从头开始。先更新软件源然后装编译工具链。之所以先装build-essential是因为后面有几个Python包需要现场编译没有gcc和make会直接失败。接着把Apache、PHP、MySQL和git一次性装好。sudo apt-get update sudo apt-get install -y build-essential python-dev python-pip git sudo apt-get install -y apache2 php libapache2-mod-php php-mysql sudo apt-get install -y mysql-server ffmpeg注意这里的python-dev和python-pip都是针对Python 2的包Ubuntu 16.04默认源里就有。如果你的系统已经更新到很新的版本源里可能找不到这两个包了需要先装Python 2本身再从源码装pip。装完之后先做一轮环境自检确认每个组件都能执行php -v mysql --version ffmpeg -version apachectl -v这轮检查非常值得能第一时间发现哪个包根本没装上而不是等配置到一半才报错。3.2 安装Python依赖VATIC的Python脚本依赖NumPy、SciPy、OpenCV、Pillow和MySQLdb。Python 2环境下MySQL的Python驱动是python-mysqldb这个包名跟Python 3时代的PyMySQL完全是两回事不要搞混。如果后面你要在Python 3环境里跑就得改代码里的import细节不少。我当时的安装命令如下sudo apt-get install -y python-numpy python-scipy python-opencv python-mysqldb sudo pip install pillow imageio提示千万不要用pip install opencv-python来装这个项目的依赖这个包是给Python 3的轮子Python 2里直接安装会报版本不支持。老老实实用系统源里的python-opencv最稳。3.3 手动放一个更稳的ffmpegUbuntu 16.04软件源自带的ffmpeg版本虽老胜在稳定处理常规H.264视频没毛病。不过我项目里的视频文件普遍比较大抽帧压力不低所以我还是手动下载了一个静态编译的新版ffmpeg解压后放到/usr/local/bin这样它会在系统自带的旧版本之前被优先调用。sudo cp ffmpeg /usr/local/bin/ sudo chmod x /usr/local/bin/ffmpeg放好之后执行which ffmpeg确认输出的是/usr/local/bin/ffmpeg而不是/usr/bin/ffmpeg否则后续抽帧脚本可能调用到老版本出现一些诡异的参数兼容问题。3.4 PHP和Apache扩展不能少PHP要连接MySQL需要php-mysql扩展Apache要支持伪静态和前端路由必须开启mod_rewrite这一步装包时不会自动启用要手动操作sudo a2enmod rewrite sudo service apache2 restart这里多说一句很多人后面前端页面能打开但接口全部404大概率就是mod_rewrite没启用或者虚拟主机配置里AllowOverride没有设为All。这一个问题我后面专门有一节讲但提前确认能省很多时间。4. 克隆VATIC并配置虚拟主机4.1 下载代码到服务器代码我放在/opt/vatic这样跟其他项目隔离得比较清楚而且路径短配置时不容易打错。需要注意权限问题不要把整个目录都留给root后面改代码、跑脚本都不方便。cd /opt sudo git clone https://github.com/cvondrick/vatic.git sudo chown -R $(whoami):$(whoami) /opt/vaticVATIC仓库的目录结构大概会包含www、scripts、config.py、requirements.txt几个关键部分。www是Web根目录所有浏览器访问的PHP和JS都在里面scripts是Python命令行工具config.py是数据库连接等总配置入口。每个版本的目录命名可能略有差异以实际拉下来的仓库为准。提示如果你的网络拉GitHub不稳定clone失败是常有的事换个时间段重试或者用国内可用的镜像源都行这不影响部署后续步骤。4.2 创建MySQL数据库和专用用户MySQL启动之后通过root进入命令行创建数据库和用户。我强烈建议单独建一个应用专用账号别让VATIC以root身份连数据库否则一旦页面存在注入风险整个数据库都暴露了。CREATE DATABASE vatic CHARACTER SET utf8mb4; CREATE USER vaticuserlocalhost IDENTIFIED BY vaticpass; CREATE USER vaticuser127.0.0.1 IDENTIFIED BY vaticpass; GRANT ALL PRIVILEGES ON vatic.* TO vaticuserlocalhost; GRANT ALL PRIVILEGES ON vatic.* TO vaticuser127.0.0.1; FLUSH PRIVILEGES;这里同时建了localhost和127.0.0.1两个用户原因是Python的MySQLdb和PHP连接MySQL时采用的socket类型可能不同一个走本地socket一个走TCP。后面如果发现连接总是失败大概率就是漏了其中一个。4.3 修改配置文件VATIC的数据库配置在config.py里把默认的配置改成你刚创建的用户名、密码和库名# config.py 中的数据库连接部分 database { host: localhost, user: vaticuser, password: vaticpass, dbname: vatic, }改完配置后先用一个最简单的Python语句验证数据库连接串对不对别等部署完了再回来排查。cd /opt/vatic python -c import MySQLdb; conn MySQLdb.connect(uservaticuser, passwdvaticpass, dbvatic); print(数据库连接OK)这一步能通说明Python到MySQL的链路没问题后面PHP出问题就是PHP侧的事排查范围能缩小一半。4.4 配置Apache虚拟主机在/etc/apache2/sites-available/下创建一个站点配置文件把DocumentRoot指到/opt/vatic/www并配置目录选项。VirtualHost *:80 ServerName vatic.local DocumentRoot /opt/vatic/www Directory /opt/vatic/www Options FollowSymLinks AllowOverride All Require all granted /Directory /VirtualHost启用站点并重启Apachesudo a2ensite vatic.conf sudo service apache2 restart访问http://服务器IP/如果能看到页面而不是默认的Apache欢迎页说明Web层基本通了。如果只是空白或者403优先检查目录权限和DocumentRoot路径。5. 数据库初始化和业务配置5.1 导入数据库初始化脚本VATIC的建表语句一般以SQL文件形式存在于仓库里常见位置是misc/schema.sql或install/schema.sql。找到后用命令导入mysql -uvaticuser -pvaticpass vatic /opt/vatic/schema.sql导入完成后用SHOW TABLES确认一下表结构是否存在。我遇到过导入时因为SQL语句里用了CHARSETutf8而建库时指定的是utf8mb4两者混在一起导致部分表建不出来。这种情况可以把SQL文件里的字符集统一替换成utf8mb4再导入。5.2 处理用户编译和登录验证VATIC原生设计是为众包场景准备的登录和账号体系默认对接众包平台的身份验证。但内部工具链根本不需要这套直接把验证逻辑绕过去或者手动插入一条管理员用户记录就行。我的做法是浏览代码搜索user和create_user相关的函数搞清楚数据结构之后在users表里插入一条带admin标记的记录然后把配置里强制校验身份的开关关掉。这一步没有任何安装教程会细讲但恰恰是很多人部署完打开页面却无法创建任务的直接原因。5.3 先跑通抽帧验证配置完数据库之后别着急在网页端创建正式任务先用命令行脚本把一段测试视频抽帧验证ffmpeg和Python之间的调用链是否通畅。cd /opt/vatic python scripts/extract.py --input sample.mp4 --output /tmp/vatic_frames --rate 5参数--rate 5表示每5帧取1帧也就是每1秒约抽6帧。执行完去/tmp/vatic_frames目录数一下图片数量正常情况下应该约等于视频总帧数除以5。如果抽出来是零张优先检查ffmpeg路径和环境变量如果数量对不上可能是视频帧率处理有偏差可以降低采样率再试。6. 标注系统的实际使用流程6.1 创建标注任务的关键参数Web页面能够正常访问之后进入系统创建一个新任务需要填写视频文件路径、采样率、目标类别列表。这里的视频路径是服务器上的实际路径不是本地上传路径所以要把视频先放到VATIC能访问的目录里。目标类别用英文逗号分隔比如person,car,bicycle这些类别最终会成为导出XML里的标注标签。还有最关键的一项任务输出目录的写权限。Apache的运行用户通常是www-data如果输出目录是root创建的标注结果保存时会直接失败而且前台页面经常不报错只往后台日志里写一条权限异常。这个坑让我白折腾过一个多小时。6.2 画框与修正的操作逻辑进入标注界面后页面左边是当前视频帧右边是目标列表和属性区域。操作流程很简单先找到目标首次出现的关键帧用鼠标拖一个初始框选择类别然后点击自动跟踪按钮后台会生成后续若干帧的预测框。接下来就是逐帧快速检查对跟丢或跑偏的框手动修正确认无误后保存。实际使用时你会很快体会到半自动跟踪的边界目标运动平缓、形变小的视频跟踪效果非常省力但遇到遮挡、目标快速交叉、画面剧烈抖动的时候后续预测框基本不能用得老老实实手工一帧帧校正。所以创建任务时不要把采样率设得太高否则修正工作量会非常大。6.3 导出训练数据标注完成后用导出脚本把MySQL里的框坐标转成PASCAL VOC格式的XML。VATIC原生导出的就是这个格式包含每帧每个目标的类别和边界框坐标。如果你想转成YOLO的txt格式或者COCO的json写个几十行的小脚本转换就行坐标数据都在数据库里不会丢。我建议导出之前先在后台统计一下任务里已完成和未完成的帧段数量。VATIC对漏标的帧段往往直接跳过如果你不注意检查导出文件会少掉某些目标训练时模型就像瞎了一只眼很难排查。7. 遇到过的坑和解决办法7.1 MySQL连接失败密码明明是对的这个问题的头号嫌疑是用户主机匹配。MySQL的localhost和127.0.0.1是两个不同的host单独建了localhost用户后Python通过TCP连接可能还是会被拒绝。解决方法是同时创建这两个用户我在4.2节已经演示了。另一个常见原因是MySQL 5.7以后新装的系统默认采用auth_socket或caching_sha2_password认证插件老版本PHP的mysql扩展不支持这种新插件需要把VATIC用户的认证方式改回mysql_native_passwordALTER USER vaticuserlocalhost IDENTIFIED WITH mysql_native_password BY vaticpass; ALTER USER vaticuser127.0.0.1 IDENTIFIED WITH mysql_native_password BY vaticpass;7.2 页面能打开但全站404页面能打开说明静态资源正常接口全部404说明伪静态路由没生效。按三个顺序排查Apache是否启用了mod_rewrite虚拟主机配置里AllowOverride是否为All最后用apachectl -t检查配置语法。我那次就是AllowOverride写成了None改过来重启Apache就正常了。VATIC前端框架大量使用伪路径方式访问PHP后台Rewrite失效时所有后台接口都会返回404。这个坑很隐蔽因为没有明确的报错只是看似“页面坏了”。7.3 Python脚本报ImportError: No module named cv2.cv这就是我在2.3节提过的OpenCV新旧接口不兼容。如果不想花大量时间改旧代码我给代码加了一个兼容层在脚本开头统一做别名映射把旧的cv2.cv调用替换成新接口等价实现。这个方案改动小能快速恢复大部分核心功能。当然更彻底的做法是把跟踪算法模块升级到OpenCV 4的API但这相当于重写一小半后台代码我建议先跑通全流程然后按需改造。7.4 ffmpeg抽帧很慢如果服务器核心数少、内存有限抽帧过程会明显拖慢整个任务创建。我的处理方法有两个一是降采样率从每2帧抽1帧改成每5帧抽1帧数据量直接少一大半二是把视频先用ffmpeg缩放到不大于1280x720的分辨率抽帧再快不少。对于目标检测数据集720p的标注精度通常已经够用太高分辨率反而让标注员眼睛受累。注意抽帧是IO密集CPU密集的混合任务别在服务器业务高峰期大批量跑。我试过同时开好几个抽帧任务直接把内存占满最后系统进入swap疯狂换页所有标注请求都开始卡顿。7.5 中文标签乱码数据库建库时如果没用utf8mb4默认字符集会落成latin1中文类别名存进去就是问号。另外PHP连接MySQL的session也要执行SET NAMES utf8mb4否则链路中某个环节还是会转码。我建议在启动服务前统一检查数据库、数据表、连接串三处的字符集设置这个检查最多几分钟但漏掉的返工时间按小时算。8. 最后说一点使用体会真正把VATIC在这个裸环境里跑起来之后团队连续用它标完了几千帧数据。我个人最大的体会是装这类老工具最难的不是装软件包而是学会跟历史版本的代码共存。它的部分设计还停留在众包时代的思维方式跟今天主流的深度学习工具链比确实不算贴心但半自动跟踪的核心思路放到当下依然能打尤其在视频目标检测数据生产上它比很多现代标注平台更省力。最后分享一个我一直沿用的技巧启动服务前一定要把config.py里的日志控件打开VATIC跑批处理任务时会在后台输出详尽日志。这些日志就是判断抽帧、跟踪、保存流程是否健康的关键比反复刷新网页碰运气靠谱得多。如果你手里的服务器内存不紧张把日志目录放到tmpfs上标注高峰期能明显减少磁盘IO抖动整个系统用起来更跟手。