emby高级参数

This commit is contained in:
mtvpls
2026-01-08 19:45:39 +08:00
parent 198272f2e0
commit 3d30258f4e
7 changed files with 231 additions and 26 deletions
+87
View File
@@ -3426,6 +3426,10 @@ const EmbyConfigComponent = ({
Password: '',
UserId: '',
isDefault: false,
// 高级选项
removeEmbyPrefix: false,
appendMediaSourceId: false,
transcodeMp4: false,
});
// 从配置加载源列表
@@ -3460,6 +3464,10 @@ const EmbyConfigComponent = ({
Password: '',
UserId: '',
isDefault: false,
// 高级选项
removeEmbyPrefix: false,
appendMediaSourceId: false,
transcodeMp4: false,
});
setEditingSource(null);
setShowAddForm(false);
@@ -3912,6 +3920,85 @@ const EmbyConfigComponent = ({
</button>
</div>
{/* 高级选项 */}
<div className='border-t border-gray-200 dark:border-gray-700 pt-4 mt-4'>
<h4 className='text-sm font-medium text-gray-700 dark:text-gray-300 mb-3'>
</h4>
{/* 选项1: 播放链接移除/emby前缀 */}
<div className='flex items-center justify-between mb-3'>
<div className='flex-1'>
<label className='text-sm font-medium text-gray-700 dark:text-gray-300'>
/emby前缀
</label>
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
/emby
</p>
</div>
<button
onClick={() => setFormData({ ...formData, removeEmbyPrefix: !formData.removeEmbyPrefix })}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
formData.removeEmbyPrefix ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
formData.removeEmbyPrefix ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
{/* 选项2: 拼接MediaSourceId参数 */}
<div className='flex items-center justify-between mb-3'>
<div className='flex-1'>
<label className='text-sm font-medium text-gray-700 dark:text-gray-300'>
MediaSourceId参数
</label>
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
PlaybackInfo API MediaSourceId
</p>
</div>
<button
onClick={() => setFormData({ ...formData, appendMediaSourceId: !formData.appendMediaSourceId })}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
formData.appendMediaSourceId ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
formData.appendMediaSourceId ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
{/* 选项3: 转码mp4 */}
<div className='flex items-center justify-between mb-3'>
<div className='flex-1'>
<label className='text-sm font-medium text-gray-700 dark:text-gray-300'>
mp4
</label>
<p className='text-xs text-gray-500 dark:text-gray-400 mt-1'>
使 stream.mp4 Static
</p>
</div>
<button
onClick={() => setFormData({ ...formData, transcodeMp4: !formData.transcodeMp4 })}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
formData.transcodeMp4 ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-700'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
formData.transcodeMp4 ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
</div>
{/* 操作按钮 */}
<div className='flex gap-3 pt-4'>
<button
+18 -16
View File
@@ -28,21 +28,23 @@ export async function GET(request: NextRequest) {
// 获取所有剧集
const allEpisodes = await client.getEpisodes(itemId);
episodes = allEpisodes
.sort((a, b) => {
if (a.ParentIndexNumber !== b.ParentIndexNumber) {
return (a.ParentIndexNumber || 0) - (b.ParentIndexNumber || 0);
}
return (a.IndexNumber || 0) - (b.IndexNumber || 0);
})
.map((ep) => ({
id: ep.Id,
title: ep.Name,
episode: ep.IndexNumber || 0,
season: ep.ParentIndexNumber || 1,
overview: ep.Overview || '',
playUrl: client.getStreamUrl(ep.Id),
}));
episodes = await Promise.all(
allEpisodes
.sort((a, b) => {
if (a.ParentIndexNumber !== b.ParentIndexNumber) {
return (a.ParentIndexNumber || 0) - (b.ParentIndexNumber || 0);
}
return (a.IndexNumber || 0) - (b.IndexNumber || 0);
})
.map(async (ep) => ({
id: ep.Id,
title: ep.Name,
episode: ep.IndexNumber || 0,
season: ep.ParentIndexNumber || 1,
overview: ep.Overview || '',
playUrl: await client.getStreamUrl(ep.Id),
}))
);
}
return NextResponse.json({
@@ -55,7 +57,7 @@ export async function GET(request: NextRequest) {
poster: client.getImageUrl(item.Id, 'Primary'),
year: item.ProductionYear?.toString() || '',
rating: item.CommunityRating || 0,
playUrl: item.Type === 'Movie' ? client.getStreamUrl(item.Id) : undefined,
playUrl: item.Type === 'Movie' ? await client.getStreamUrl(item.Id) : undefined,
},
episodes: item.Type === 'Series' ? episodes : [],
});
@@ -61,7 +61,7 @@ export async function GET(
let client = await getEmbyClient(embyKey);
// 构建 Emby 原始播放链接
let embyStreamUrl = client.getStreamUrl(itemId);
let embyStreamUrl = await client.getStreamUrl(itemId);
// 构建请求头,转发 Range 请求
const requestHeaders: HeadersInit = {};
@@ -81,7 +81,7 @@ export async function GET(
const { embyManager } = await import('@/lib/emby-manager');
embyManager.clearCache();
client = await getEmbyClient(embyKey);
embyStreamUrl = client.getStreamUrl(itemId);
embyStreamUrl = await client.getStreamUrl(itemId);
videoResponse = await fetch(embyStreamUrl, {
headers: requestHeaders,
});
+2 -2
View File
@@ -68,7 +68,7 @@ export async function GET(request: NextRequest) {
year: item.ProductionYear?.toString() || '',
douban_id: 0,
desc: item.Overview || '',
episodes: [client.getStreamUrl(item.Id)],
episodes: [await client.getStreamUrl(item.Id)],
episodes_titles: [item.Name],
subtitles: subtitles.length > 0 ? [subtitles] : [],
proxyMode: false,
@@ -102,7 +102,7 @@ export async function GET(request: NextRequest) {
year: item.ProductionYear?.toString() || '',
douban_id: 0,
desc: item.Overview || '',
episodes: allEpisodes.map((ep) => client.getStreamUrl(ep.Id)),
episodes: await Promise.all(allEpisodes.map((ep) => client.getStreamUrl(ep.Id))),
episodes_titles: allEpisodes.map((ep) => {
const seasonNum = ep.ParentIndexNumber || 1;
const episodeNum = ep.IndexNumber || 1;