Merge pull request #335 from sususu98/enhancement/transcodesInfo

Enhancement/transcodes info
This commit is contained in:
Thegan Govender
2025-03-22 10:21:37 +02:00
committed by GitHub
7 changed files with 89 additions and 17 deletions

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@
/backend/backup-data
.vscode
.idea
.env
# production
/build

View File

@@ -8,7 +8,8 @@
"STATISTICS": "统计",
"SETTINGS": "设置",
"ABOUT": "关于",
"LOGOUT": "注销"
"LOGOUT": "注销",
"TIMELINE": "时间线"
},
"HOME_PAGE": {
"SESSIONS": "会话",
@@ -18,8 +19,8 @@
},
"SESSIONS": {
"NO_SESSIONS": "未找到活动会话",
"DIRECT_PLAY": "",
"TRANSCODE": ""
"DIRECT_PLAY": "直接播放",
"TRANSCODE": "转码"
},
"STAT_CARDS": {
"MOST_VIEWED_MOVIES": "最多观看电影",
@@ -77,7 +78,8 @@
"TAB_CONTROLS": {
"OVERVIEW": "总览",
"ACTIVITY": "活动",
"OPTIONS": "选项"
"OPTIONS": "选项",
"TIMELINE": "时间线"
},
"ITEM_ACTIVITY": "活动项目",
"ACTIVITY_TABLE": {
@@ -116,7 +118,7 @@
"PURGE_LIBRARY_CACHE_WITH_ACTIVITY": "清除已缓存媒体库、项目及活动",
"PURGE_LIBRARY_ITEMS_CACHE": "仅清除已缓存媒体库项目",
"PURGE_LIBRARY_ITEMS_CACHE_WITH_ACTIVITY": "仅清除已缓存媒体库项目和活动",
"PURGE_ACTIVITY": "确定要除已选中的播放活动?"
"PURGE_ACTIVITY": "确定要除已选中的播放活动?"
},
"ERROR_MESSAGES": {
"FETCH_THIS_ITEM": "从 Jellyfin 获取此项目",
@@ -179,7 +181,7 @@
"SIZE": "大小",
"JELLYFIN_URL": "Jellyfin URL",
"EMBY_URL": "Emby URL",
"EXTERNAL_URL": "External URL",
"EXTERNAL_URL": "外部链接",
"API_KEY": "API 密钥",
"API_KEYS": "API 密钥",
"KEY_NAME": "密钥名称",
@@ -231,7 +233,7 @@
"Backup": "备份 Jellystat"
},
"SEARCH": "搜索",
"TOTAL": "Total",
"TOTAL": "总计",
"LAST": "过去",
"SERIES": "剧集",
"SEASON": "季",
@@ -284,7 +286,7 @@
"SOURCE_DETAILS": "媒体源信息",
"DIRECT": "直接播放",
"TRANSCODE": "转码",
"DIRECT_STREAM": "",
"DIRECT_STREAM": "直接串流",
"USERNAME": "用户名",
"PASSWORD": "密码",
"LOGIN": "登录",
@@ -306,5 +308,10 @@
"TIMEZONE": "时区",
"POSTCODE": "邮编",
"X_ROWS_SELECTED": "已选中 {ROWS} 行",
"SUBTITLES": ""
"TRANSCODE_REASONS": "转码原因",
"SUBTITLES": "字幕",
"TIMELINE_PAGE": {
"TIMELINE": "时间线",
"EPISODES": "集数"
}
}

View File

@@ -215,6 +215,37 @@ export default function ActivityTable(props) {
);
},
},
{
accessorKey: "PlayMethod",
header: i18next.t("TRANSCODE"),
size: 150,
Cell: ({ row }) => {
row = row.original;
if (row.PlayMethod === "Transcode") {
return (
<span className="text-warning" style={{ fontWeight: 'bold' }}>
{i18next.t("TRANSCODE")}
{row.TranscodingInfo ?
<span>
{!row.TranscodingInfo.IsVideoDirect &&
<span> ({i18next.t("VIDEO")})</span>
}
{!row.TranscodingInfo.IsAudioDirect &&
<span> ({i18next.t("AUDIO")})</span>
}
</span> : ""
}
</span>
);
} else if (row.PlayMethod === "DirectPlay") {
return <span className="text-success" style={{ fontWeight: 'bold' }}>{i18next.t("DIRECT")}</span>;
} else if (row.PlayMethod === "DirectStream") {
return <span className="text-info" style={{ fontWeight: 'bold' }}>{i18next.t("DIRECT_STREAM")}</span>;
} else {
return <span style={{ color: 'gray' }}>-</span>;
}
},
},
{
accessorKey: "DeviceName",
header: i18next.t("ACTIVITY_TABLE.DEVICE"),

View File

@@ -61,7 +61,13 @@ function Row(logs) {
<TableRow>
<TableCell ><strong><Trans i18nKey={"VIDEO"}/></strong></TableCell>
<TableCell colSpan="2" style={{textTransform:"uppercase"}}><strong>{data.TranscodingInfo ? (data.TranscodingInfo?.IsVideoDirect ? i18next.t("DIRECT") :i18next.t("TRANSCODE")):i18next.t("DIRECT")}</strong></TableCell>
<TableCell colSpan="2" style={{textTransform:"uppercase"}}><strong>
{data.PlayMethod === "DirectStream" ?
i18next.t("DIRECT_STREAM") :
(data.TranscodingInfo ?
(data.TranscodingInfo?.IsVideoDirect ? i18next.t("DIRECT") : i18next.t("TRANSCODE")) :
i18next.t("DIRECT"))}
</strong></TableCell>
</TableRow>
<TableRow>
@@ -108,7 +114,13 @@ function Row(logs) {
<TableRow>
<TableCell ><strong><Trans i18nKey={"AUDIO"}/></strong></TableCell>
<TableCell colSpan="2" style={{textTransform:"uppercase"}}><strong>{data.TranscodingInfo ? (data.TranscodingInfo?.IsAudioDirect ? i18next.t("DIRECT") :i18next.t("TRANSCODE")):i18next.t("DIRECT")}</strong></TableCell>
<TableCell colSpan="2" style={{textTransform:"uppercase"}}><strong>
{data.PlayMethod === "DirectStream" ?
i18next.t("DIRECT_STREAM") :
(data.TranscodingInfo ?
(data.TranscodingInfo?.IsAudioDirect ? i18next.t("DIRECT") : i18next.t("TRANSCODE")) :
i18next.t("DIRECT"))}
</strong></TableCell>
</TableRow>
<TableRow>
@@ -135,7 +147,16 @@ function Row(logs) {
<TableCell className="py-0 pb-3" >{data.MediaStreams ? data.MediaStreams.find(stream => stream.Type === 'Audio' && stream.Index===data.PlayState?.AudioStreamIndex)?.Language?.toUpperCase() : '-'}</TableCell>
</TableRow>
{data.TranscodingInfo && data.TranscodingInfo?.TranscodeReasons && data.TranscodingInfo.TranscodeReasons.length > 0 && (
<>
<TableRow>
<TableCell colSpan="3"><strong><Trans i18nKey={"TRANSCODE_REASONS"}/></strong></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-0 pb-3" colSpan="3">{data.TranscodingInfo.TranscodeReasons.join(", ")}</TableCell>
</TableRow>
</>
)}
</React.Fragment>
);

View File

@@ -122,7 +122,7 @@ function ItemActivity(props) {
// }
filteredData = filteredData.filter((item) =>
streamTypeFilter == "All"
streamTypeFilter === "All"
? true
: item.PlayMethod === (config?.IS_JELLYFIN ? streamTypeFilter : streamTypeFilter.replace("Play", "Stream"))
);
@@ -155,6 +155,9 @@ function ItemActivity(props) {
<option value="DirectPlay">
<Trans i18nKey="DIRECT" />
</option>
<option value="DirectStream">
<Trans i18nKey="DirectStream" /> (<Trans i18nKey="DirectStream" />)
</option>
</FormSelect>
</div>

View File

@@ -11,7 +11,7 @@ function PlaybackMethodStats(props) {
const translations = {
DirectPlay: <Trans i18nKey="DIRECT" />,
Transcode: <Trans i18nKey="TRANSCODE" />,
DirectStream: <Trans i18nKey="DIRECT_STREAM" />,
DirectStream: <Trans i18nKey="DIRECT_STREAM" />
};
const chartIcon = <BarChartGroupedLineIcon size={"100%"} />;
@@ -79,9 +79,15 @@ function PlaybackMethodStats(props) {
return (
<ItemStatComponent
base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl}
data={data.map((stream) =>
stream.Name == "DirectPlay" ? { ...stream, Name: translations.DirectPlay } : stream.Name == "DirectStream" ? { ...stream, Name: translations.DirectStream } : { ...stream, Name: translations.Transcode }
)}
data={data.map((stream) => {
if (stream.Name === "DirectPlay") {
return { ...stream, Name: translations.DirectPlay };
} else if (stream.Name === "DirectStream") {
return { ...stream, Name: translations.DirectStream };
} else {
return { ...stream, Name: translations.Transcode };
}
})}
icon={chartIcon}
heading={<Trans i18nKey="STAT_CARDS.CONCURRENT_STREAMS" />}
units={<Trans i18nKey="UNITS.STREAMS" />}

View File

@@ -226,6 +226,9 @@ function UserActivity(props) {
<option value="DirectPlay">
<Trans i18nKey="DIRECT" />
</option>
<option value="DirectStream">
<Trans i18nKey="DIRECT_STREAM" />
</option>
</FormSelect>
</div>