AzuraCast:自托管一体化网络电台管理套件

news/2025/11/15 18:08:11/文章来源:https://www.cnblogs.com/qife122/p/19225980

AzuraCast:自托管一体化网络电台管理套件

项目描述

AzuraCast是一个自托管、一体化的网络电台管理套件。通过其简单的安装程序和强大直观的Web界面,您可以在几分钟内启动一个完全可用的网络电台。AzuraCast适用于各种类型和规模的网络电台,旨在运行在最经济的VPS虚拟主机上。

功能特性

  • 完整的电台管理:提供从流媒体广播到节目编排的完整解决方案
  • 多格式支持:支持Icecast、HLS等多种流媒体协议和格式
  • 智能自动DJ:支持播放列表调度、歌曲请求和实时流媒体
  • 共享编码器:可选功能,可在具有相同比特率和格式的多个流之间共享编码器,显著降低CPU消耗
  • Liquidsoap 2.4.0集成:更新的流媒体后端,包含关键错误修复和改进
  • 用户权限管理:细粒度的权限控制系统,支持全局和电台级别权限
  • API接口:完整的RESTful API,支持第三方集成
  • 多语言支持:支持多种语言界面
  • 主题定制:可定制的用户界面主题
  • 备份恢复:完整的数据库和媒体备份恢复功能

安装指南

系统要求

  • PHP 8.1或更高版本
  • MariaDB/MySQL数据库
  • Redis缓存(可选但推荐)
  • 足够的磁盘空间用于媒体存储

安装步骤

  1. 下载项目

    git clone https://github.com/AzuraCast/AzuraCast.git
    cd AzuraCast
    
  2. 运行安装程序

    ./docker.sh setup
    
  3. 或使用传统安装方式

    php bin/console azuracast:setup
    
  4. 访问管理界面
    安装完成后,通过浏览器访问您的服务器IP地址即可开始配置。

Docker安装(推荐)

AzuraCast提供完整的Docker支持,包含所有必要的依赖项:

curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/main/docker.sh > docker.sh
chmod a+x docker.sh
./docker.sh setup

使用说明

基本配置

  1. 创建第一个电台

    • 登录管理后台
    • 点击"添加电台"
    • 配置基本信息、流媒体设置和自动DJ
  2. 上传媒体文件

    • 通过Web界面上传音乐文件
    • 或使用SFTP直接上传到媒体目录
  3. 配置播放列表

    • 创建定时播放列表
    • 设置播放规则和顺序
    • 配置交叉淡入淡出效果

API使用示例

获取当前播放信息:

curl https://your-azuracast-instance.com/api/nowplaying

获取电台列表:

curl https://your-azuracast-instance.com/api/stations

命令行工具

AzuraCast提供丰富的命令行工具:

# 同步当前播放信息
php bin/console azuracast:sync:nowplaying# 备份系统
php bin/console azuracast:backup /path/to/backup.zip# 恢复备份
php bin/console azuracast:restore /path/to/backup.zip# 清除缓存
php bin/console azuracast:cache:clear

核心代码

权限控制系统

<?php
declare(strict_types=1);namespace App;final class Acl
{public function __construct(private readonly ReloadableEntityManagerInterface $em,private readonly EventDispatcherInterface $dispatcher) {$this->reload();}/*** 检查用户是否具有特定权限*/public function userAllowed(User $user, string $permission, ?Station $station = null): bool{$userRoles = $user->roles;foreach ($userRoles as $role) {if ($this->roleHasPermission($role, $permission, $station)) {return true;}}return false;}/*** 重新加载ACL缓存*/public function reload(): void{// 从数据库加载权限配置$sql = $this->em->createQuery(<<<'DQL'SELECT IDENTITY(rp.station) AS station_id, IDENTITY(rp.role) AS role_id, rp.action_name FROM App\Entity\RolePermission rpDQL);$this->actions = [];foreach ($sql->toIterable() as $row) {if ($row['station_id']) {$this->actions[$row['role_id']]['stations'][$row['station_id']][] = $row['action_name'];} else {$this->actions[$row['role_id']]['global'][] = $row['action_name'];}}}
}

当前播放缓存系统

<?php
declare(strict_types=1);namespace App\Cache;final class NowPlayingCache
{private const int NOWPLAYING_CACHE_TTL = 180;/*** 设置电台的当前播放信息*/public function setForStation(Station $station,?NowPlaying $nowPlaying): void {$this->populateLookupCache($station);$stationCacheItem = $this->getStationCache($station->short_name);$stationCacheItem->set($nowPlaying);$stationCacheItem->expiresAfter(self::NOWPLAYING_CACHE_TTL);$this->cache->saveDeferred($stationCacheItem);$this->cache->commit();}/*** 获取所有电台的当前播放信息*/public function getForAllStations(bool $publicOnly = false): array{$lookupCacheItem = $this->getLookupCache();if (!$lookupCacheItem->isHit()) {return [];}$np = [];$lookupCache = (array)$lookupCacheItem->get();foreach ($lookupCache as $stationInfo) {if ($publicOnly && !$stationInfo['is_public']) {continue;}$npRowItem = $this->getStationCache($stationInfo['short_name']);$npRow = $npRowItem->isHit() ? $npRowItem->get() : null;if ($npRow instanceof NowPlaying) {$np[] = $npRow;}}return $np;}
}

自定义资源管理系统

<?php
declare(strict_types=1);namespace App\Assets;abstract class AbstractCustomAsset implements CustomAssetInterface
{/*** 获取资源路径*/public function getPath(): string{$pattern = sprintf($this->getPattern(), '');return $this->getBasePath() . '/' . $pattern;}/*** 获取资源URL*/public function getUrl(): string{$path = $this->getPath();if (is_file($path)) {$pattern = $this->getPattern();$mtime = filemtime($path);return $this->getBaseUrl() . '/' . sprintf($pattern,'.' . $mtime);}return $this->getDefaultUrl();}/*** 上传资源*/public function upload(ImageInterface $image, string $mimeType): void{$newImage = clone $image;$newImage->resizeDown(1500, 1500);$this->delete();$patterns = $this->getPatterns();[$pattern, $encoder] = $patterns[$mimeType] ?? $patterns['default'];$destPath = $this->getPathForPattern($pattern);$this->ensureDirectoryExists(dirname($destPath));$newImage->encode($encoder)->save($destPath);}
}

消息队列处理系统

<?php
declare(strict_types=1);namespace App\Console\Command\MessageQueue;final class ProcessCommand extends AbstractSyncCommand
{protected function execute(InputInterface $input, OutputInterface $output): int{$this->logToExtraFile('app_worker.log');$runtime = Types::int($input->getArgument('runtime'));$workerName = Types::stringOrNull($input->getOption('worker-name'), true);$this->logger->notice('Starting new Message Queue worker process.', ['runtime' => $runtime,'workerName' => $workerName,]);// 配置消息队列接收器$receivers = $this->queueManager->getTransports();// 添加事件订阅者$this->eventDispatcher->addServiceSubscriber(ClearEntityManagerSubscriber::class);$this->eventDispatcher->addServiceSubscriber(LogWorkerExceptionSubscriber::class);// 设置工作器超时$this->eventDispatcher->addSubscriber(new StopWorkerOnTimeLimitListener($runtime, $busLogger));try {$worker = new Worker($receivers, $this->messageBus, $this->eventDispatcher, $busLogger);$worker->run();} catch (Throwable $e) {$this->logger->error('Message queue error: ' . $e->getMessage(), ['workerName' => $workerName,'exception' => $e,]);return 1;}return 0;}
}

更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

公众号二维码

公众号二维码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/966431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年11月安徽省有实力的旧房翻新企业综合推荐排行榜

摘要 随着国内城市化进程加速和居民生活品质提升,2025年旧房翻新行业迎来爆发式增长,安徽省特别是合肥地区的旧房翻新需求显著上升。本文基于行业数据、用户口碑、技术实力等多维度评估,为您推荐2025年11月安徽省最…

【前缀和+差分+二分】LeetCode 2528. 最大化城市的最小电量

View Post【前缀和+差分+二分】LeetCode 2528. 最大化城市的最小电量题目 https://leetcode.cn/problems/maximize-the-minimum-powered-city/description/ 题解 以stations = [1,2,4,5,0], r = 1, k = 2为测试用例进行…

Springboot启动时记录进程ID

Springboot启动时记录进程ID 1. 背景说明 springboot项目打包成可执行jar包以后,需要通过java -jar xxx.jar启动项目.启动方式对非技术人员不太友好.所以需要项目构建时,生成一个start.bat和stop.bat的脚本.关闭采用ta…

019数据结构之栈——算法备赛 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

详细介绍:【Linux】07.Ubuntu开发环境部署

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

GESP考试报名附考试报名流程

GESP 考试报名 附考试报名流程 一、考试时间安排 1.报名时间 一般为每次认证考试前1-2个月,具体时间以GESP官网公布时间为准。 2.考试时间 CCF每年安排4次GESP认证考试,分别在3月、6月、9月和12月。2025年的考试时间…

2025 最新电缆品牌权威推荐:耐火 / 阻燃 / 智能 / 光伏等全品类优质厂商榜单,附国际认证测评

引言 随着全球电力基建、新能源产业及智能建筑的高速发展,电缆作为核心传输载体,其品质直接决定工程安全与运行效率。据国际电线电缆制造商协会(ICEA)最新测评数据显示,全球合格电缆产品仅占市场总量的 68%,32% …

2025 最新电缆制造厂家推荐!电缆品牌权威榜单发布,耐火 / 智能 / 特种电缆优选企业全解析

引言 随着全球能源转型与工业智能化加速,电缆作为核心基础设施的战略价值愈发凸显。据国际电线电缆制造商协会(ICEA)最新测评数据显示,全球优质电缆品牌市场集中度仅 32%,超 60% 的采购风险源于产品质量不达标与技…

2025年Dynamics 365 CRM的工作行情如何?

长沙爱码士IT机构对2025年Dynamics 365 CRM的工作行情做了分析和汇总,报告如下:2025 年 Dynamics 365 CRM 的工作行情整体较好,呈现出岗位需求大、薪资待遇可观、人才供应稀缺等特点,以下是具体情况:岗位需求方面…

iHaier2.0 智能协同办公模块(Doc-Collab)实现实用的方案详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

字节序浅析

定义 uint32_t value = 0x12345678 /* 如果该value保存在地址 0x20010010*/ /* 小端序:低字节在低地址 即0x78的实际地址为 0x20010010*/ /* 大端序:低字节在高地址 即0x12的实际地址为 0x20010010*/内存 堆空间一般…

2025 最新无缝钢管厂家推荐榜:国际测评认证 + 技术创新 + 全场景适配权威指南大口径无缝钢管/16Mn 无缝钢管/定制无缝钢管/厚壁无缝钢管公司推荐

引言 无缝钢管作为工业制造、能源输送等核心领域的关键材料,其品质直接影响下游产业安全运行。本次推荐榜基于国际钢铁协会(World Steel Association)与国际钢管行业协会(ISSF)联合 SGS、Intertek 两大检测机构的…

2025年硫酸钠流化床干燥机源头厂家权威推荐榜单:调味品振动流化床干燥机/大豆纤维流化床干燥机/味精振动流化床干燥机源头厂家精选

工业干燥领域技术迭代加速,硫酸钠流化床干燥机市场正迎来高效节能与智能化转型的关键时期 在化工、制药、食品等行业高效生产需求的推动下,硫酸钠流化床干燥机市场持续增长。据行业报告显示,全球流化床干燥机市场规…

MX Round 24 解题报告

T1 因为不能有中间插入的颜色,所以我们可以把所有操作改为在当前已操作区间的左右两侧扩展。 于是用栈实现即可。 T2 Fun Fact:两个错误的暴力得到了一个正确的算法。 首先,我们用暴力算法打一下表,发现每一次选取…

2025 最新钢结构源头厂家推荐排行榜,聚焦优质供应与专业服务精选榜单美标 / 欧标钢结构 / 环保设备 / 水泥矿山 / 机械设备钢结构厂家推荐

引言 在无缝钢管、网架及钢结构领域,市场需求正朝着高规格、定制化、绿色化方向快速升级,但行业乱象仍存:部分企业缺乏核心技术导致产品精度不足,网架结构稳定性达标率低,无缝钢管材质不符合国标要求;资质挂靠、…

当下市面上靠谱的平移门服务商

摘要 随着城市化进程加速和智能化需求提升,2025年平移门行业迎来新一轮技术革新,市场增长率预计达15%。智能平移门因其安全、便捷、高效的特点,已成为政府机构、商业综合体、交通枢纽等场所的首选方案。本文基于技术…

2025年11月中国伸缩门源头厂家口碑推荐榜单

摘要 随着智慧城市建设加速推进,2025年中国伸缩门行业迎来技术升级与市场扩容双重机遇。智能防夹技术、物联网集成控制系统及节能电机成为行业主流配置,市场规模预计突破80亿元(数据来源:中国安防行业协会《2025智…

简单了解数组

数组 int[] sh;//首选方法 int sh[];//效果相同,适用于c,c++方法 int[] sh=new int[数组大小];//静态初始化 int[] x={1,34,52,37,3};//动态初始化 int[] x=new int[10]; x[0]=33;反转数组 import java.util.Scanner…

2025年目字扣订制厂家权威推荐榜单:塑料扣具/箱包插扣/五金插扣源头厂家精选

在箱包、服装及户外装备行业蓬勃发展的推动下,目字扣作为关键的调节与固定件,其市场需求持续增长,定制化与专业化已成为行业竞争焦点。 目字扣,又称三档扣,虽是小配件,却是决定背包、腰带等产品“好用与否”的关…

# 第10章 指针和结构体

10.1 指针 一、什么是指针 指针(Pointer):变量的地址,通过它能找到以它为地址的内存单元。 例子1:理解指针概念 #include <bits/stdc++.h> using namespace std; int main(){int x=10;int* p=&x; // 定义…