.kael/skills/xray-player-control/SKILL.md
Analisa logs de sessoes de video do Player X-Ray (Globo), identifica travamentos, problemas de buffer, erros de rede e performance HLS.js. Controla player remotamente enviando comandos e executando JavaScript no dispositivo.
npx skillsauth add gugaio/kael xray-player-controlInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
$0 = sessionId (obrigatorio para logs)$1 = deviceId (opcional para logs, obrigatorio para comandos)https://player-xray.globo.comhttp://127.0.0.1:8888 (usar apenas quando explicitamente solicitado)| Rota | Metodo | Descricao |
|------|--------|-----------|
| /api/sessions/{sessionId}/logs | GET | Logs sem deviceId |
| /api/devices/{deviceId}/sessions/{sessionId}/logs | GET | Logs com deviceId |
| /api/devices/{deviceId}/messages/sync | POST | Comandos sincronos (com confirmacao) |
| /api/devices/{deviceId}/messages | POST | Comandos fire-and-forget (apenas code_generated) |
cursor: Posicao inicial (padrao: "0")pageSize: Logs por pagina (padrao: 50, maximo: 5000). Sempre use 5000 para captura completa.order: asc (cronologico) ou desc (mais recentes primeiro)Use a tool exec para chamadas curl. Exemplos:
curl -s 'https://player-xray.globo.com/api/sessions/{sessionId}/logs?pageSize=5000&cursor=0&order=asc'
Com deviceId:
curl -s 'https://player-xray.globo.com/api/devices/{deviceId}/sessions/{sessionId}/logs?pageSize=5000&cursor=0&order=asc'
TODOS os comandos usam /messages/sync (exceto code_generated). Sempre inclua correlation_id unico.
curl -X POST 'https://player-xray.globo.com/api/devices/{deviceId}/messages/sync' \
-H 'Content-Type: application/json' \
-d '{"command":"play","correlation_id":"play-001"}'
curl -X POST 'https://player-xray.globo.com/api/devices/{deviceId}/messages' \
-H 'Content-Type: application/json' \
-d '{"command":"code_generated","param":"(async () => { /* codigo */ })();"}'
| Comando | Param | Descricao |
|---------|-------|-----------|
| play | - | Inicia/retoma reproducao |
| pause | - | Pausa reproducao |
| stop | - | Para reproducao completamente |
| seek | segundos (numero) | Navega para tempo especifico |
| volume | 0-100 (numero) | Define nivel de volume |
| mute | true/false | Ativa/desativa mudo |
| Comando | Param | Descricao |
|---------|-------|-----------|
| open_language_menu | - | Abre menu de idiomas |
| close_language_menu | - | Fecha menu de idiomas |
| toggle_language_menu | - | Alterna menu de idiomas |
| set_subtitle | id da trilha (ex: "pt-BR") | Define legenda |
| set_audio | id da trilha (ex: "en") | Define audio |
| Comando | Param | Descricao |
|---------|-------|-----------|
| get_current_state | - | Retorna estado atual do player |
| get_device_volume | - | Retorna volume/mudo atual |
| code_instruction | instrucao (string) | Envia instrucao de codigo |
/messages/sync: para TODOS os comandos exceto code_generatedcorrelation_id obrigatorio: use valor unico (ex: UUID, timestamp)/messages (sem sync): apenas para code_generated e code_instruction(async () => { ... })()console.log, erros com console.errorthis.container.play()
this.container.pause()
this.container.stop()
this.container.seek(timeInSeconds)
this.container.mute()
this.container.setVolume(volume) // 0-100
this.container.currentTime // propriedade: posicao atual
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
(async () => {
try {
console.log('Iniciando sequencia: play por 5s e pausar')
await this.container.play()
await sleep(5000)
await this.container.pause()
console.log('Sequencia concluida')
} catch (error) {
console.error('Erro:', error)
}
})()
(async () => {
try {
const positions = [10, 30, 60, 120]
for (const pos of positions) {
console.log(`Seek para ${pos}s`)
await this.container.seek(pos)
await sleep(3000)
}
console.log('Teste de seeks concluido')
} catch (error) {
console.error('Erro:', error)
}
})()
{
"data": [
{
"date_time": "2026-01-07T20:25:08.732Z",
"level_name": "INFO|WARN|ERROR",
"message": "[\"Playback paused\",{\"player_type\":\"hlsjs\"}]"
}
],
"next_cursor": 20,
"has_more": true
}
Importante: O campo message e JSON stringificado. Sempre faca parse para acessar dados estruturados.
| Tipo | Mensagem | Significado |
|------|----------|-------------|
| Travamento | Playback stalling due to low buffer | Buffer < 2s = problema serio |
| Rede | FRAG_LOAD_ERROR | Falha ao carregar fragmento |
| Rede | MANIFEST_LOAD_ERROR | Falha ao carregar manifest |
| Buffer | BUFFER_APPENDED | Dados adicionados ao buffer |
| Buffer | BUFFER_FLUSHED | Buffer limpo |
| Qualidade | LEVEL_SWITCHED | Mudanca de qualidade/bitrate |
curl -s 'https://player-xray.globo.com/api/sessions/{sessionId}/logs?pageSize=5000&cursor=0&order=asc' > /tmp/xray-logs.json
echo "Total de logs:" $(jq '.data | length' /tmp/xray-logs.json)
echo "Erros:" $(jq '[.data[] | select(.level_name == "ERROR")] | length' /tmp/xray-logs.json)
echo "Warnings:" $(jq '[.data[] | select(.level_name == "WARN")] | length' /tmp/xray-logs.json)
echo "Stalling:" $(jq '[.data[] | select(.message | contains("stall"))] | length' /tmp/xray-logs.json)
jq -r '.data[] |
select(.message | contains("stall") or contains("error") or contains("ERROR") or
contains("paused") or contains("playing") or contains("seek")) |
"\(.date_time) [\(.level_name)] \(.message)"' /tmp/xray-logs.json
jq -r '.data[] |
select(.message | contains("stall")) |
(.message | fromjson) as $msg |
"\(.date_time) - \($msg[0]) - Detalhes: \($msg[1] | tostring)"' /tmp/xray-logs.json
jq -r '.data[] |
select(.level_name == "ERROR") |
"\(.date_time) - \(.message)"' /tmp/xray-logs.json | head -20
jq -r '.data[] |
select(.message | contains("buffer")) |
(.message | fromjson) as $msg |
"\(.date_time) - \($msg[0]) - \($msg[1].bufferLen // $msg[1])"' /tmp/xray-logs.json
jq -r '.data[] |
select(.message | contains("LEVEL") or contains("quality")) |
"\(.date_time) - \(.message)"' /tmp/xray-logs.json
playing e primeiro stall, FRAG_LOAD_ERROR proximosFRAG_LOAD_ERROR ou MANIFEST_LOAD_ERRORAo gerar relatorio, use este formato:
# Analise de Logs - Player X-Ray
## Informacoes da Sessao
- **Device**: {deviceId}
- **Session**: {sessionId}
- **Periodo**: {inicio} ate {fim}
## Resumo Executivo
{problema principal}
## Problemas Identificados
### 1. {tipo}
- **Severidade**: Alta / Media / Baixa
- **Primeira Ocorrencia**: {timestamp}
- **Frequencia**: {n vezes}
- **Causa Provavel**: {hipotese}
## Metricas
- Buffer Medio: {valor}s
- Travamentos: {n}
- Erros de Rede: {n}
- Mudancas de Qualidade: {n}
## Recomendacoes
1. {acao especifica}
tools
Use quando o usuario quiser consultar dados do Youbora/NPAW (views, plays, erros, QoE, tipo vod/live, janelas de tempo e granularidade). Priorize Clark/MCP; use a chamada HTTP/MD5 local apenas como fallback.
testing
Diagnostica se o roteamento de skills foi correto para a mensagem atual. Use quando o usuario quiser validar auto-selecao de skill, checar relevancia da escolha, ou depurar por que uma skill foi (ou nao foi) aplicada.
testing
Use when the task is to save, curate, or update project-specific knowledge inside a project space under `.kael/projects/<project>/`. Best for deciding whether to update `PROJECT.md` or create thematic Markdown documents such as `params.md`, `networking.md`, or `playback.md`.
tools
Opera servidores MCP configurados no Kael via tools dedicadas mcp_list e mcp_call.