Агент: медиа-тулсет (search/info/play) на Jellyfin + скилл media
- MEDIA_TOOLSET + MediaToolExecutor: search (поиск с лимитом), info (детали), play (проверки+запуск) - JellyfinMediaSource: обёртка JellyfinClient (search/item) с защитой userId - agentPlayMedia: проверки (очки на связи, видео скачано на очки, звук на телефоне) → watch с позицией - PhoneActions.watch(startPositionMs), JellyfinItem.ProductionYear - скилл app-phone/skills/media.md (frontmatter: name/description) - MediaToolsTest: 22 кейса — всего 142 теста зелёные
This commit is contained in:
@@ -18,6 +18,8 @@ data class JellyfinItem(
|
||||
val Id: String,
|
||||
val Name: String? = null,
|
||||
val Type: String? = null, // Movie/Series/Episode/Folder/CollectionFolder
|
||||
/** Год релиза (Movie/Series); в ответах может отсутствовать. */
|
||||
val ProductionYear: Int? = null,
|
||||
val Overview: String? = null,
|
||||
val ImageTags: Map<String, String>? = null, // Primary есть — есть постер
|
||||
val SeriesName: String? = null, // для эпизодов
|
||||
|
||||
@@ -91,8 +91,15 @@ class PhoneActions(
|
||||
* Включить на очках: зеркало должно быть done → PlayVideo с ЛОКАЛЬНЫМ путём на очках.
|
||||
* Стриминг запрещён: [localVideoPath] — file://... с диска очков (или пустой — не играем).
|
||||
* Звук — на телефоне: [phoneAudioReady] — скачаны ли аудио-дорожки на телефон.
|
||||
* [startPositionMs] — стартовая позиция (seek для запуска с середины).
|
||||
*/
|
||||
suspend fun watch(itemId: String, audioIndex: Int = 0, localVideoPath: String = "", phoneAudioReady: Boolean = true): String {
|
||||
suspend fun watch(
|
||||
itemId: String,
|
||||
audioIndex: Int = 0,
|
||||
localVideoPath: String = "",
|
||||
phoneAudioReady: Boolean = true,
|
||||
startPositionMs: Long = 0,
|
||||
): String {
|
||||
val item = jellyfin.item(userId, itemId) ?: return "элемент $itemId не найден"
|
||||
val status = mirror.mirrorByItem(itemId)
|
||||
val files = status?.files
|
||||
@@ -107,7 +114,7 @@ class PhoneActions(
|
||||
}
|
||||
|
||||
val title = item.Name ?: itemId
|
||||
sender.send(PlayVideo(itemId = itemId, title = title, videoUrl = localVideoPath, audioIndex = audioIndex))
|
||||
sender.send(PlayVideo(itemId = itemId, title = title, videoUrl = localVideoPath, audioIndex = audioIndex, startPositionMs = startPositionMs))
|
||||
// очки не помнят scale между запусками — при старте просмотра шлём текущий
|
||||
if (state.scale != 1f) sender.send(SetScale(state.scale))
|
||||
state.mode = GlassesMode.MOVIE
|
||||
|
||||
Reference in New Issue
Block a user