Ampache 常用命令与运维实战(核心篇)

bin/cli 扫描与元数据修复、Ampache/Subsonic 双 API 真实调用回显、流播放与转码对照、backup-db.sh 备份,附六条排障实录。

AmpacheAmpache音频流媒体NAS 自托管2026/10/28

Ampache 常用命令与运维实战(核心篇)

曲库扫描、文件级元数据修复、两套 API 的真实调用与踩坑、数据库备份与导出——本文是 Ampache 8.3.0 的日常运维手册。所有命令与回显均来自真实服务器实测(环境为 《Ampache Docker Compose 部署实战》 搭建的单机站)。

CLI 体系总览

Ampache 8 的命令行入口统一为应用目录下的 bin/cli。直接执行不带参数会打印完整命令清单(按动词分组):

php /var/www/bin/cli

实测清单(节选,保留本文用到的组):

run
  run:addCatalog                       Add a new catalog
  run:updateCatalog                    Perform catalog actions for all files of a catalog. If no options are given, the defaults actions -ceagt are assumed
  run:updateCatalogFile                Perform catalog actions for a single file
  run:updateCatalogFolder              Perform catalog actions for a single folder
  run:updateDb                         Update the database collation and charset
  run:websocket                        Run the websocket server that listen-along broadcasting needs
show
  show:debug                           Show a system status and environment report
  show:version                         Version
export
  export:albumArt                      Export album art
  export:catalog                       Export catalog metadata to a file
  export:databaseArt                   Export all database art to local_metadata_dir

其余组还有用户管理(add:user 等)与管理维护命令,php bin/cli <command> --help 可查每个命令的参数。两个最基础的体检命令实测:

php /var/www/bin/cli show:version
8.3.0
php /var/www/bin/cli show:debug
System
  Version:   8.3.0
  Structure: public
  PHP:       8.5.12
  Last cron: Never
Environment
  [OK] PHP version
  [OK] PDO
  [OK] PDO MySQL
  [OK] session
  [OK] JSON
  [OK] hash
  [OK] intl
  [OK] cURL
  [OK] GD
  [!!] memory limit
  [OK] dependencies folder

Last cron: Never 说明计划任务(定时扫描/清理)从未跑过——生产环境需要自行配置 cron(Web 界面或 run:updateCatalog 的定时调用);[!!] memory limit 是默认 PHP 内存上限偏紧的提示,大曲库需调 memory_limit。

Catalog 扫描与媒体管理

建目录曲库

php /var/www/bin/cli run:addCatalog music /media

music 是曲库名,/media 是服务器上的媒体目录。建好后曲库登记进数据库但还没有歌曲,需要执行一次扫描。用数据库确认曲库已登记:

mariadb -uampache -pq1w2e3r4 ampache -e "select id,name,catalog_type,enabled from catalog"

实测输出:

id	name	catalog_type	enabled
1	music	local	1

扫描导入

php /var/www/bin/cli run:updateCatalog music -a -t

-a 收录新增文件,-t 重新生成目录结构;不带任何参数时默认执行 -ceagt(清理/变更/新增/校验/结构全套)。扫描完成的验证(查数据库):

songs
6
name            year
Analog Dreams   2024
Field Notes     2023

6 首测试曲目、2 张专辑入库成功。常规校验扫描(读文件核对数据库):

php /var/www/bin/cli run:updateCatalog music -e -t -a

实测输出:

Update table mapping, counts and delete garbage data
local.catalog: update_folder_map
local.catalog: update_folder_counts
------------------
Time: 00:02

元数据修复后必须单文件重扫

真实场景:修了文件的标签(比如补年份),再跑上面的整库校验扫描,数据库里的元数据纹丝不动。实测对照:

修复 FLAC 文件的年份标签(ffmpeg 原地重写):

ffmpeg -i "05 - Deep Field.flac" -c copy -metadata date=2024 "05 - Deep Field.new.flac"
mv "05 - Deep Field.new.flac" "05 - Deep Field.flac"
ffprobe -v quiet -show_entries format_tags=date -of json "05 - Deep Field.flac"
{
    "format": {
        "tags": {
            "date": "2024"
        }
    }
}

文件确实带上了 date=2024,但 run:updateCatalog music -e -t -a 之后数据库里该曲的 year 仍是 0。此时用单文件重扫强制重读:

php /var/www/bin/cli run:updateCatalogFile music "/media/05 - Deep Field.flac" -a -e

实测输出:

Reading File: "/media/05 - Deep Field.flac"

单文件重扫后专辑随之合并:

id	name	year	songs
1	Field Notes	2023	3
4	Analog Dreams	2024	3

顺带两个实测教训:

  • run:updateCatalogFile 的参数顺序是 <catalogName> <filePath>,只传文件路径会把路径当曲库名解析;它也不认识 -t,实测直接报 Option "-t" not registered。
  • 专辑按「名称+艺术家+年份」聚合,年份缺失会拆出 year=0 的同名专辑——测试曲库 FLAC 补上年份重扫后 4 张专辑合并回 2 张,就是这个机制的直接体现。

导出曲库清单

php /var/www/bin/cli export:catalog /var/www/backup/catalog-export.csv -c 1

实测输出:

Exported catalog metadata to /var/www/backup/catalog-export.csv

导出的 CSV(实测内容):

ID,Title,Artist,Album,Length,Track,Year,"Date Added",Bitrate,Played,File
4,"Open Water","Northway Trio","Field Notes",0:40,0,2023,"10/28/26, 9:16 AM",15-VBR,,"/media/06 - Open Water.ogg"
3,"Silver Rain","Northway Trio","Field Notes",0:45,1,2023,"10/28/26, 9:16 AM",312-CBR,1,"/media/03 - Silver Rain.mp3"
1,"Northern Line","Northway Trio","Field Notes",0:45,2,2023,"10/28/26, 9:16 AM",312-CBR,,"/media/04 - Northern Line.mp3"
2,"Deep Field","Echo Valley","Analog Dreams",0:40,0,2024,"10/28/26, 9:16 AM",95-VBR,1,"/media/05 - Deep Field.flac"
6,"Morning Signal","Echo Valley","Analog Dreams",0:45,1,2024,"10/28/26, 9:16 AM",312-CBR,,"/media/01 - Morning Signal.mp3"

-c 0 导出全部曲库;第二个位置参数可选 itunes 格式。这份清单适合做曲库盘点与迁移比对。

Ampache API 实测

API 入口是 server/json.server.php(JSON)与 server/xml.server.php(XML)。除 ping 外所有方法都需要握手换取的 auth token。

握手(handshake)

认证串是双重 SHA-256:先算密码的 SHA-256,再拼接 Unix 时间戳求 SHA-256,即 auth = sha256(timestamp + sha256(password)),时间戳与服务器时差不能太大。

TS=$(date +%s)
H1=$(printf %s "q1w2e3r4" | sha256sum | cut -d' ' -f1)
AUTH=$(printf %s "${TS}${H1}" | sha256sum | cut -d' ' -f1)
curl -s "http://<服务器IP>:8137/server/json.server.php?action=handshake&user=admin&timestamp=$TS&auth=$AUTH&version=8.0.0&client=quzuo-test"

实测回显(节选,字段落盘):

{
 "auth": "056917369abf3d971e4106d5a2ec099f",
 "streamtoken": "b228ac865ee81991f100b97de68812c11ef40405",
 "api": "8.1.0",
 "session_expire": "2026-10-28T10:44:00+00:00",
 "update": "2026-10-28T09:27:38+00:00",
 "max_song": 6,
 "max_album": 4,
 "max_artist": 2,
 "songs": 6,
 "albums": 4,
 "artists": 2,
 "genres": 2,
 "catalogs": 1,
 "username": "admin"
}

auth 就是后续请求的会话令牌(有效期默认 3600 秒,对应 session_length),streamtoken 是流播放链接里 ssid 参数的值。注意 8.3.0 已移除旧版可预测的 MD5(username) 会话,别再按老脚本硬编码。

方法调用与版本陷阱

拿到 token 后即可调数据方法。这里有一个版本陷阱:老教程里的 get_artists 在 API 6+ 已更名,实测直接得到 Invalid Request:

curl -s "http://<服务器IP>:8137/server/json.server.php?action=get_artists&auth=$AUTH&limit=2"
{
    "error": {
        "errorCode": "4705",
        "errorAction": "get_artists",
        "errorType": "system",
        "errorMessage": "Invalid Request"
    }
}

改用新名 artists:

curl -s "http://<服务器IP>:8137/server/json.server.php?action=artists&auth=$AUTH&limit=2"

实测返回两张专辑对应的两位艺术家(total_count: 2,genre 名为 Electronic/Folk)。单曲详情:

curl -s "http://<服务器IP>:8137/server/json.server.php?action=songs&auth=$AUTH&limit=1"

实测回显(保留实测字段值):

{
 "id": "2",
 "title": "Deep Field",
 "artist": { "id": "2", "name": "Echo Valley", "prefix": "", "basename": "Echo Valley" },
 "album": { "id": "4", "name": "Analog Dreams", "prefix": null, "basename": "Analog Dreams" },
 "catalog": "1",
 "bitrate": 97970,
 "mime": "audio/flac",
 "size": 489851,
 "time": 40,
 "url": "http://10.89.63.1:8137/play/index.php?ssid=b228ac865ee81991f100b97de68812c11ef40405&type=song&oid=2&uid=1&player=api&name=Echo%20Valley%20-%20Deep%20Field.flac",
 "filename": "/media/05 - Deep Field.flac"
}

XML 格式在 xml.server.php,实测 action=artists&limit=1 回显片段:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <total_count>2</total_count>
  <artist id="2">
    <name><![CDATA[Echo Valley]]></name>
    <genre id="2">
      <name><![CDATA[Electronic]]></name>
    </genre>
    <albumcount>2</albumcount>
    <songcount>3</songcount>
    <art><![CDATA[http://10.89.63.1:8137/images/blankalbum.png]]></art>
</artist>

流播放

songs 返回的 url 即流地址,直接请求:

curl -s -o /dev/null -w "raw: HTTP %{http_code} type=%{content_type} size=%{size_download}\n" \
  "http://<服务器IP>:8137/play/index.php?ssid=$STREAMTOKEN&type=song&oid=2&uid=1&player=api&format=raw"
curl -s -o /dev/null -w "mp3: HTTP %{http_code} type=%{content_type} size=%{size_download}\n" --max-time 90 -H "Range: bytes=0-" \
  "http://<服务器IP>:8137/play/index.php?ssid=$STREAMTOKEN&type=song&oid=2&uid=1&player=api&format=mp3"

实测输出:

raw: HTTP 200 type=audio/flac size=489851
mp3: HTTP 200 type=audio/mpeg size=640883

format=raw 原样输出 FLAC;format=mp3 触发服务端转码(40 秒音频 640883 字节 ≈ 128 kbps)。转码开关与码率模板的配置关系见 《Ampache 配置参数详解》。

Subsonic API 实测

Subsonic 入口是 rest/<方法>.view,与 Ampache API 同源不同认证。认证有两个坑:

坑一:t/s(token+salt)认证用的不是登录密码,而是用户档案里的专用 Subsonic 密码。用登录密码算 MD5 token 实测被拒:

curl -s "http://<服务器IP>:8137/rest/ping.view?u=admin&t=00000000000000000000000000000000&s=abc123&v=1.16.1&c=quzuo-test&f=json"
{
    "subsonic-response": {
        "status": "failed",
        "version": "1.16.1",
        "type": "ampache",
        "serverVersion": "8.3.0",
        "openSubsonic": true,
        "error": {
            "code": 40,
            "message": "Wrong username or password.",
            "helpUrl": "https://ampache.org/api/subsonic"
        }
    }
}

要先在 Web 界面的用户资料里设置 Subsonic 专用密码,t = md5(专用密码 + salt) 才能通过。坑二之外,p= 直接传密码(或其十六进制编码)是最省事的实测路径:

curl -s "http://<服务器IP>:8137/rest/ping.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&f=json"
{
    "subsonic-response": {
        "status": "ok",
        "version": "1.16.1",
        "type": "ampache",
        "serverVersion": "8.3.0",
        "openSubsonic": true
    }
}

兼容层自报家门:协议 1.16.1、服务端 8.3.0、openSubsonic: true——主流 Subsonic 客户端均可直连。

常用浏览方法

# 艺术家索引
curl -s "http://<服务器IP>:8137/rest/getArtists.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&f=json"
# 专辑列表
curl -s "http://<服务器IP>:8137/rest/getAlbumList2.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&f=json&type=alphabeticalByName&size=4"

实测专辑列表(合并元数据修复后):

al-4 Analog Dreams | Echo Valley | songs: 3 | year: 2024
al-1 Field Notes | Northway Trio | songs: 3 | year: 2023
# 专辑内曲目
curl -s "http://<服务器IP>:8137/rest/getAlbum.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&f=json&id=al-1"

实测回显(节选):

album: al-1 Field Notes year 2023
so-4 Open Water ogg 40
so-3 Silver Rain mp3 45
so-1 Northern Line mp3 45

搜索与播放统计:

curl -s "http://<服务器IP>:8137/rest/search3.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&f=json&query=field"
curl -s "http://<服务器IP>:8137/rest/scrobble.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&id=so-3"

scrobble 实测返回 status="ok",播放计数随之累加。

Subsonic 流播放与限速转码

curl -s -o s1.ogg -w "raw: HTTP %{http_code} type=%{content_type} size=%{size_download}\n" \
  "http://<服务器IP>:8137/rest/stream.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&id=so-4"
curl -s -o s2.mp3 -w "128k: HTTP %{http_code} type=%{content_type} size=%{size_download}\n" --max-time 90 \
  "http://<服务器IP>:8137/rest/stream.view?u=admin&p=q1w2e3r4&v=1.16.1&c=quzuo-test&id=so-1&maxBitRate=128&format=mp3"
file s1.ogg s2.mp3

实测输出:

raw: HTTP 200 type=application/ogg size=82051
128k: HTTP 200 type=audio/mpeg size=1802610
s1.ogg: Ogg data, Vorbis audio, mono, 44100 Hz, ~96000 bps
s2.mp3: Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 320 kbps, 44.1 kHz, Monaural

两个实测发现:一是 Subsonic 端点不要带 f=json(流端点会被路由到 HTML 分支返回空 body);二是 maxBitRate=128 时回源参数确实带了 bitrate=128000,但落盘文件是 320 kbps——码率参数并未如请求预期传导,对码率敏感的部署要用 encode_args 定制并实测验证。

数据库备份与恢复

官方镜像自带 backup-db.sh,从 ampache.cfg.php 读取数据库凭据,无需传参:

docker exec ampache-8.3.0-web backup-db.sh

实测输出:

Backing up database 'ampache' to /var/www/backup/2026-10-28.sql
Backup complete: /var/www/backup/2026-10-28.sql

备份文件落在容器内 /var/www/backup,编排时已把宿主机 ./data/backup 挂到这里,落盘即得(实测目录):

2026-10-28.sql              # backup-db.sh 产物
ampache-db-20261028.sql     # 手工 mariadb-dump 产物
catalog-export.csv          # export:catalog 产物

手工等价命令(需要恢复时用的凭据来自配置文件):

mariadb-dump -uampache -pq1w2e3r4 ampache > ampache-db-$(date +%Y%m%d).sql

实测产物 157669 字节,文件头自报服务端版本 11.8.9-MariaDB-ubu2404。恢复方向:

mariadb -uampache -pq1w2e3r4 ampache < ampache-db-20261028.sql

数据库之外别忘了两样:data/config(配置文件含数据库密码)与 data/media(音频本体)——官方文档原话是「Only the database is backed up this way」,其余用常规文件备份覆盖。另有 admin:exportSchema 可把当前库结构导出为种子 SQL,用于全新部署比对。

排障实录

以下六条全部来自本文实测过程的真实定位记录:

1. 整库 verify 不刷新已替换文件的元数据。 现象:ffmpeg 重写文件标签后 run:updateCatalog -e -t -a 照跑无误,但年份/专辑不变。定位:对比 ffprobe 文件标签与数据库 song 表字段值。解法:run:updateCatalogFile <catalog> <file> -a -e 单文件强制重读,重扫后同名专辑自动合并。

2. Subsonic 播放返回 HTTP 200 但 0 字节。 现象:rest/stream.view 返回 text/html 空 body,客户端侧表现为「连上了但播不出」。开启 debug 日志后看到关键两行:

(StreamingHandler) -> Stream proxy: http://localhost:8137/play/index.php?ssid=...&type=song&oid=1&uid=1&...
(StreamingHandler) -> Stream error: Failed to connect to localhost port 8137 after 0 ms: Could not connect to server

根因:Subsonic 流由服务端代理回源,回源地址取自请求 Host;测试时用 localhost:8137 访问,而服务进程内部访问不到这个地址。解法:用服务器自身可达的地址访问(本例 10.89.63.1:8137),日志立刻变为成功的 Stream proxy 记录,流正常输出。部署启示:发布给客户端的地址必须是服务端自己也能访问的地址(反向代理/防火墙场景重点核对)。

3. 转码 429 的定位与对照实验。 初始默认配置(transcode_flac 未授权、transcode_cmd 未启用)下请求 format=mp3 播放 FLAC 得到 HTTP 429 空响应。定位路径:配置语义(transcode_TYPE = {allowed|required|false},默认 false)→ 源码中播放动作的转码否决逻辑。修复后对照实测:

transcode OFF: HTTP 200 type=audio/flac size=489851   # transcode_cmd 可用但格式未授权时回退原格式
transcode ON:  HTTP 200 type=audio/mpeg size=640883   # 授权后正常转码

即 429 出现在「请求转码格式 + 转码命令未就绪」的组合下;仅关闭格式授权而转码命令可用时,部分路径回退为原格式直出。修复方式:开启 transcode_flac = "allowed" 并确认 transcode_cmd = "ffmpeg"。

4. 用错 API 方法名得到 4705。 现象:action=get_artists 返回 errorCode 4705 Invalid Request。定位:源码确认 API 6+ 方法更名。解法:artists/songs 等新名;老集成脚本升级 8.x 前先过一遍 API 变更说明。

5. Subsonic t/s 认证 BADAUTH。 现象:md5(登录密码+salt) 得到 code 40 Wrong username or password.。定位:源码中 token 认证读取的是用户档案的专用 Subsonic 密码(subsonic secret),不是登录密码。解法:Web 界面用户资料里设置专用密码后重算 token,或直接用 p= 认证(内网环境)。

6. run:updateCatalogFile 参数顺序坑。 现象:只传文件路径时报参数错位、-t 选项直接抛 Option "-t" not registered。解法:该命令签名是 <catalogName> <filePath>,选项只有 -a/-e 等,整库动作才用 run:updateCatalog。

参考