Skip to content

Instantly share code, notes, and snippets.

@aabytt
Last active April 29, 2024 11:14
Show Gist options
  • Save aabytt/bddbb1bcf031a050d89a89aeee3a6737 to your computer and use it in GitHub Desktop.
Save aabytt/bddbb1bcf031a050d89a89aeee3a6737 to your computer and use it in GitHub Desktop.
more useful stuff on lg webos

Playling a link with standard LG webOS player

  • id - id of the player app, com.webos.app.mediadiscovery for webOS 6+, com.webos.app.photovideo for webOS 3.x-5.x, com.webos.app.smartshare for webOS 1.0-2.x
  • fullPath - url of the video file
  • fileName - name of the video displayed in player. Filename is remembered by the player to continue playback from exit timestamp

from a web app

webOS.service.request("luna://com.webos.applicationManager", {
           method: "launch",
           parameters: { "id": "com.webos.app.photovideo", "params": {"payload":[{
		"fullPath":"https://media.w3.org/2010/05/sintel/trailer.mp4",
		"artist":"",
		"subtitle":"",
		"dlnaInfo":{"flagVal":4096,"cleartextSize":"-1","contentLength":"-1","opVal":1,"protocolInfo":"http-get:*:video/x-matroska:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000","duration":0},
		"mediaType":"VIDEO",
		"thumbnail":"",
		"deviceType":"DMR",
		"album":"",
		"fileName":"trailer",
		"lastPlayPosition":-1}]}},
           onSuccess: function (inResponse) {
               console.log("The app is launched");
           },
           onFailure: function (inError) {
               console.log("Failed to launch the app");
               console.log("[" + inError.errorCode + "]: " + inError.errorText);
               return;
           }
       });

from shell

luna-send-pub -n 1 -f luna://com.webos.applicationManager/launch '{"id": "com.webos.app.photovideo", "params": {"payload":[{"fullPath":"https://media.w3.org/2010/05/sintel/trailer.mp4","artist":"","subtitle":"","dlnaInfo":{"flagVal":4096,"cleartextSize":"-1","contentLength":"-1","opVal":1,"protocolInfo":"http-get:*:video/x-matroska:DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000","duration":0},"mediaType":"VIDEO","thumbnail":"","deviceType":"DMR","album":"","fileName":"trailer","lastPlayPosition":-1}]}}'

Turning screen backlight off (root)

# 1
luna-send -f -n 1 luna://com.webos.service.settings/setSystemSettings '{"category":"picture","settings":{"energySaving":"screen_off","energySavingModified":"true"}}'
//screen will turn back on with any remote key

# 2
luna-send -n 1 "luna://com.webos.service.tvpower/power/turnOffScreen" '{}'
luna-send -n 1 "luna://com.webos.service.tvpower/power/turnOnScreen" '{}'

Making screenshot with timestamp filename

luna-send -n 1 -f 'luna://com.webos.service.capture/executeOneShot' '{"path":"/tmp/'"$(date +%Y_%m_%d_%H-%M-%S)"'_capture.png","method":"DISPLAY","format":"PNG"}'

Getting mediaId

mediaId is assigned by webos media server to any opened media pipeline. Value is required to perform direct com.webos.media calls to control playback of videos.

Read from web app

document.querySelector('video').mediaId

Public Luna calls that return video details including mediaId (may not be supported on older webOS versions)

luna://com.webos.service.videooutput/getStatus luna://com.webos.media/getForegroundAppInfo

Private Luna call

luna://com.webos.media/getActivePipelines

Undocumented com.webos.media calls

Direct use of com.webos.media by application developers is strongly discouraged. Instead, the media interfaces native to a particular application framework (e.g. Web, QT, SDL/NDL) should be used. However some standard web apis (like managing subtitles) are not supported leaving us no choice rather to use direct calls.

Subtitles show/hide

method setSubtitleEnable parameters:

  • mediaId
  • enable - true to show subtitles, false to hide subtitles

Example

webOS.service.request("luna://com.webos.media", {
	    method:"setSubtitleEnable",
	    parameters: { 
			"mediaId": "_MQUBT01X5MiTj4",
			"enable": true
			},
	      onSuccess: function (result) {
                 console.log(JSON.stringify(result));
		}
	      },
	      onFailure: function (result) {
	        console.log( "[fail][" + result.errorCode + "] " + result.errorText );
	        }
	 });

Select subtitle and audiotracks

method selectTrack parameters:

  • mediaId
  • type - audio for audiotracks, text for subtitletracks
  • index - number of track (0...n)

Subtitle size

method setSubtitleFontSize parameters:

  • mediaId
  • fontSize - values: 0 for tiny, 1 - small, 2 - standard (default), 3 - large, 4 - huge

Subtitle color

method setSubtitleColor parameters:

  • mediaId
  • color - values: 0 - yellow, 1 - red, 2 - white (default), 3 - green, 4 - blue, 5 - gray

Subtitle position

method setSubtitlePosition parameters:

  • mediaId
  • position - values: -3for lowest position, -2, -1,0 (default), 1, 2, 3, 4 for highest position

Subtitle opacity

method setSubtitleCharacterOpacity parameters:

  • mediaId
  • charOpacity - values: from 0 for fully transparent to 255 for non-transparent (default)

Subtitle character color

(seems to do the same as setSubtitleColor but some different values) method setSubtitleCharacterColor parameters:

  • mediaId
  • charColor - values: black, white (default), yellow, red, green, blue

Subtitle background opacity

method setSubtitleBackgroundOpacity parameters:

  • mediaId
  • bgOpacity - values: from 0 for fully transparent (default) to 255 for non-transparent

Subtitle background color

method setSubtitleBackgroundColor parameters:

  • mediaId
  • bgColor - values: black (default), white, yellow, red, green, blue

Subtitle window opacity

method setSubtitleWindowOpacity parameters:

  • mediaId
  • windowOpacity - values: from 0 for fully transparent (default) to 255 for non-transparent

Subtitle window color

method setSubtitleWindowColor parameters:

  • mediaId
  • windowColor - values: black (default), white, yellow, red, green, blue

Subtitle encoding

method setSubtitleEncoding parameters:

  • mediaId
  • encoding - values: ISO8859-1, ISO6937, UTF-8, WINDOWS-1252, WINDOWS-1250, ISO8859-4, WINDOWS-1251, WINDOWS-1256, WINDOWS-1253, ISO8859-8, ISO8859-9, ISO8859-11, WINDOWS-1258, BIG5, GB2312, EUCKR, Shift_JIS

External subtitles

method setSubtitleSource parameters:

  • mediaId
  • uri link to subtitles file (i.e. http://some.website/filename.srt or local file file:///tmp/usb/sda/sda1/filename.srt)
  • preferredEncodings - optional parameter

Subtitles sync

method setSubtitleSync parameters:

  • mediaId
  • sync - values: +-sync in milliseconds (i.e. -350, 200, 1500, etc)

Playback speed

method setPlayRate parameters:

  • mediaId
  • playRate - values from 0.1 to 2.0, default is 1.0
  • audioOutput - true, audio is played only up to x2 playback rate

Subscribe to events

To get video detailed data like number of embedded audio and subtitle tracks may be needed to subscribe to pipeline events and parse sourceInfo generated after media is loaded (https://www.webosose.org/docs/reference/ls2-api/com-webos-media/#sourceinfo-1)

method subscribe parameters:

  • mediaId
  • subscribe - true

To unsubscribe use method unsubscribe with only parameter mediaId

Example of sourceInfo object

{"sourceInfo":{"numPrograms":1,"container":"mkv","seekable":true,"trickable":true,"programInfo":[{"duration":1295552,"numAudioTracks":4,"audioTrackInfo":[{"bitRate":0,"language":"ru","codec":"ac3","sampleRate":48,"channels":2,"audioType":0},{"bitRate":0,"language":"ru","codec":"ac3","sampleRate":48,"channels":2,"audioType":0},{"bitRate":0,"language":"ru","codec":"ac3","sampleRate":48,"channels":2,"audioType":0},{"bitRate":0,"language":"en","codec":"ac3","sampleRate":48,"channels":6,"audioType":0} ],"numVideoTracks":1,"videoTrackInfo":[{"angleNumber":0,"level":3.1,"width":1280,"height":720,"codec":"H264","profile":"high","frameRate":23.976,"progressive":true} ],"numSubtitleTracks":2,"subtitleTrackInfo":[{"language":"ru","type":"text"},{"language":"en","type":"text"} ]} ],"mediaId":"_MQUBT01X5MiTj4"}}

Tracks order

Audiotrack may have disposition.default tag. WebOS 4+ reads this tag and puts the track marked as default into the first position of tracks list (index 0)

@thecode
Copy link

thecode commented Mar 11, 2022

This is very nice, do you know how to do process similar for playing audio? or how do I get this information? Thanks

@aabytt
Copy link
Author

aabytt commented Mar 12, 2022

@thecode here is an example, works on webOS 5, not sure if Music app exists on lower versions

luna-send-pub -n 1 -f luna://com.webos.applicationManager/launch '{"id": "com.webos.app.music", "params": {"payload": [ { "mediaType": "MUSIC", "deviceType": "DMR", "fileName": "Kalimba", "fullPath": "https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba-online-audio-converter.com_-1.wav", "thumbnail": "", "subtitle": "", "lastPlayPosition": -1, "album": "", "artist": "", "dlnaInfo": { "protocolInfo": "http-get:*:audio\/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000", "contentLength": "-1", "duration": 0, "opVal": 1, "flagVal": 0, "cleartextSize": "-1"}}]}}'

@thecode
Copy link

thecode commented Mar 12, 2022

Thanks, This is working, what is the proper way to get this information? are there any resources I can read about supported APIs ore any app which uses this I can look into it's code?

@aabytt
Copy link
Author

aabytt commented Mar 12, 2022

well, all the fun stuff is not documented by LG so we can only reverse engineer it.
study webosbrew pages for details and join openlgtv community on discord

@mahesh-logituit
Copy link

mahesh-logituit commented Jul 14, 2022

Thanks @aabytt, This is very helpful, Is it possible to launch a player under any specific element.
for example <div id="videoContainer" /> under any div element can we create player, so that we can show our custom controls on top of the player.

@aabytt
Copy link
Author

aabytt commented Jul 20, 2022

@mahesh-logituit I guess you can do it

@mahesh-logituit
Copy link

@aabytt these LS2 luna://com.webos.media APIs supported in WEBOS TV player?

@aabytt
Copy link
Author

aabytt commented Jul 25, 2022

@mahesh-logituit you mean player for TV channels?

@mahesh-logituit
Copy link

@aabytt I mean WebOS TV player for LG TV. this document may help you understand more https://webostv.developer.lge.com/api/webos-service-api/intro-lunaservice/

@willrockss
Copy link

Man, thanks a lot for that info!
Actually I am very surprised how difficult is to find documentation regarding LG TV API, especially for older version (like 3.5).

I actually still didn't find a way to install default Photo and Video app com.webos.app.photovideo into the emulator 3.5! O_o

@aabytt
Copy link
Author

aabytt commented Jun 30, 2023

@willrockss yeah, they do not share most of their api. we have to reverse engineer it in most cases.
Why would you need and app on emulator?

@willrockss
Copy link

@willrockss yeah, they do not share most of their api. we have to reverse engineer it in most cases. Why would you need and app on emulator?

I am writing a web-app (server side) to automatically play movies from my local media server (I was very glad to realize that any HTTP server fits, not just DLNA) via default Photo & Video app. It would be very handy to use an emulator for testing instead of a real TV.

@trullock
Copy link

You dont happen to know the incantation to play an mp4 from a usb device do you?

@aabytt
Copy link
Author

aabytt commented Jul 23, 2023

You dont happen to know the incantation to play an mp4 from a usb device do you?

same way just use a proper fullpath
example "fullPath":"file:///tmp/usb/sda/sda1/Big_Buck_Bunny_1080_10s_30MB.mp4"

@trullock
Copy link

@aabytt thanks very much, solved my problem! Is there a param to enable looping?

@aabytt
Copy link
Author

aabytt commented Jul 26, 2023

idk, possibly webos player has some settings to loop the playlist

@trullock
Copy link

idk, possibly webos player has some settings to loop the playlist

Forgive my ignorance, do you have any idea where to look for that? I cant find a thing on it...

@stiw47
Copy link

stiw47 commented Jan 14, 2024

Very useful info, thank you for that. Do you know maybe how would go shell command to confirm "Yes" button on current on-screen alert? I am on rooted OLED55C11LB btw. Thx.

@aabytt
Copy link
Author

aabytt commented Jan 16, 2024

Very useful info, thank you for that. Do you know maybe how would go shell command to confirm "Yes" button on current on-screen alert? I am on rooted OLED55C11LB btw. Thx.

I do not think it's possible with a shell command

@stiw47
Copy link

stiw47 commented Jan 16, 2024

Hmmm. For example, from Home Assistant, we can send button event to LG webOS. Home Assistant has LG webOS Smart TV integration which is communicate with webOS via REST API I think. I was meant if this can be done from Home Assistant via API, then most probably there is some endpoint where shell command could interact via luna://
In this particular case where I am interested to confirm "Yes" button on current on-screen alert, what I am actually doing:
I have bluetooth audio amplifier, connected to Monitor Audio speakers by wires. TV is connecting to amplifier via bluetooth. Every time when I turn on TV, I have to manually go to sound devices, switch to BT device, choose my amplifier, click on connect. I want to automate this, and since my C1 is already rooted, I can write init.d scripts (already have few of them).
So I have this for connect to BT amplifier:
luna-send -f -n 1 luna://com.webos.service.bluetooth2/a2dp/connect '{"address": "7b:b1:b9:be:82:fe"}'

(Devices are already paired before, so there is no need for that step. However, if anybody need it, there is pairing and a lot more about BT here: https://www.webosose.org/docs/guides/development/connectivity/bluetooth-guide/)

Anyway, after previous command, devices are connected, but UI alert pops-up and asking to accept this:
image

I can even switch to BT sound output with the following command:
luna-send -f -n 1 luna://com.webos.service.apiadapter/audio/changeSoundOutput '{"output": "bt_soundbar"}'

It is working, output on TV was changed to BT, but alert stay on screen, and:

  1. Either have to be confirmed manually from Magic Remote
  2. Or will disappear after some time, this will cause that sound output being reverted back to TV speaker.

So, since "Yes" button is already focused on alert, it seems that I only missing the part how to send ENTER button event from command line with luna-send - this is what I cannot find how to do.

@aabytt
Copy link
Author

aabytt commented Jan 17, 2024

What if forcing alert close with a luna call? Will it revert back to TV speaker as well?

@stiw47
Copy link

stiw47 commented Jan 17, 2024

What if forcing alert close with a luna call? Will it revert back to TV speaker as well?

I already tried exactly that one from your link and no joy. Yes, it will revert back to TV speaker when alert is closed. It seems that I have to confirm alert somehow, either if find API call to confirm or with sending ENTER button event.

This is some workflow:

  1. Sending call to connect - BT is connected, but alert appear and asking to switch to BT sound output:
    root@LGwebOSTV:~# luna-send -f -n 1 luna://com.webos.service.bluetooth2/a2dp/connect '{"address": "7b:b1:b9:be:82:fe"}'
    image

  2. Sending call to change sound output - sound output has been changed, but alert stay:
    root@LGwebOSTV:~# luna-send -f -n 1 luna://com.webos.service.apiadapter/audio/changeSoundOutput '{"output": "bt_soundbar"}'
    image

  3. Sending call to dismiss all alerts - alert has been dismissed, but sound output has been reverted back to TV speaker as well:
    root@LGwebOSTV:~# luna-send -n 1 -f -a com.webos.service.battest luna://com.webos.notification/closeAllAlerts '{}'
    image

@aabytt
Copy link
Author

aabytt commented Jan 17, 2024

Run ls-monitor and check in logs what is happening when you hit Yes button with a remote.

@stiw47
Copy link

stiw47 commented Jan 17, 2024

Great point, didn't know for ls-monitor, great.
Huh, since you recommended ls-monitor, you are probably know that logs pumps insanely fast (cause it is probably logging everything what happens on TV).

Anyway, playing fast fingers, this is something what I caught with stop it with Ctrl+C as soon as I hit ENTER button on remote:

nt":1}»
312.173 RX return       1722            com.lge.settingsservice (sYicqN1r)              com.webos.service.db (l0IbSe2C) «{"returnValue":true,"count":1}»
312.174 TX  call        1723            com.lge.settingsservice (sYicqN1r)              com.webos.service.db (l0IbSe2C)         /com/palm/luna/private/cancel    «{"token":1722}»
312.174 TX  return      839             com.lge.settingsservice (sYicqN1r)              com.webos.service.audio (hBjngH5b)      «{"method":"setSystemSettingDesc","returnValue":true}»
312.174 RX return       839             com.webos.service.audio (hBjngH5b)              com.webos.settingsservice (sYicqN1r)    «{"method":"setSystemSettingDesc","returnValue":true}»
312.174 TX  call        1725            com.lge.settingsservice (sYicqN1r)      com.webos.service.db (l0IbSe2C)         (null)          //merge  «{"query":{"from":"com.webos.settings.desc.system:1","where":[{"op":"=","prop":"key","val":"userEqualizer"},{"op":"=","prop":"app_id","val":""}]},"props":{"dbtype":"G","ui":{"active":false},"category":"sound","key":"userEqualizer"}}»
312.175 RX call 1723            com.palm.db (l0IbSe2C)          com.lge.settingsservice (sYicqN1r)              /com/palm/luna/private/cancel    «{"token":1722}»
312.175 RX call 1725            com.palm.db (l0IbSe2C)  com.lge.settingsservice (sYicqN1r)              (null)          //merge «{"query":{"from":"com.webos.settings.desc.system:1","where":[{"op":"=","prop":"key","val":"userEqualizer"},{"op":"=","prop":"app_id","val":""}]},"props":{"dbtype":"G","ui":{"active":false},"category":"sound","key":"userEqualizer"}}»
312.180 TX  return      1725            com.palm.db (l0IbSe2C)          com.lge.settingsservice (sYicqN1r)      «{"returnValue":true,"count":1}»
312.180 RX return       1725            com.lge.settingsservice (sYicqN1r)              com.webos.service.db (l0IbSe2C) «{"returnValue":true,"count":1}»
312.182 TX  call        1726            com.lge.settingsservice (sYicqN1r)              com.webos.service.db (l0IbSe2C)         /com/palm/luna/private/cancel    «{"token":1725}»
312.182 TX  return      840             com.lge.settingsservice (sYicqN1r)              com.webos.service.audio (hBjngH5b)      «{"method":"setSystemSettingDesc","returnValue":true}»
312.182 RX call 1726            com.palm.db (l0IbSe2C)          com.lge.settingsservice (sYicqN1r)              /com/palm/luna/private/cancel    «{"token":1725}»
312.182 RX return       840             com.webos.service.audio (hBjngH5b)              com.webos.settingsservice (sYicqN1r)    «{"method":"setSystemSettingDesc","returnValue":true}»
312.236 TX  call        232             com.webos.service.btaudiosrc (H4Ma5luW) com.webos.service.bluetooth2 (LpVH8he9)         (null)  /a2dp/internal/setSbcEncoderBitpool      «{"address":"7b:b1:b9:be:82:fe","bitpool":30}»
312.236 RX call 232             com.webos.service.bluetooth2 (LpVH8he9) com.webos.service.btaudiosrc (H4Ma5luW)         (null)          /a2dp/internal/setSbcEncoderBitpool      «{"address":"7b:b1:b9:be:82:fe","bitpool":30}»
312.237 TX  return      232             com.webos.service.bluetooth2 (LpVH8he9)         com.webos.service.btaudiosrc (H4Ma5luW) «{"adapterAddress":"20:28:bc:1f:de:dd","address":"7b:b1:b9:be:82:fe","returnValue":true}»
312.238 RX return       232             com.webos.service.btaudiosrc (H4Ma5luW)         com.webos.service.bluetooth2 (LpVH8he9) «{"adapterAddress":"20:28:bc:1f:de:dd","address":"7b:b1:b9:be:82:fe","returnValue":true}»
312.239 TX  call        233             com.webos.service.btaudiosrc (H4Ma5luW)         com.webos.service.bluetooth2 (LpVH8he9)         /com/palm/luna/private/cancel    «{"token":232}»
312.239 RX call 233             com.webos.service.bluetooth2 (LpVH8he9)         com.webos.service.btaudiosrc (H4Ma5luW)         /com/palm/luna/private/cancel    «{"token":232}»

So, bluetooth connection was already initiated, BT device connected. Then I remember the last line in ls-monitor, then hit the ENTER on remote to confirm the alert, and stopped monitor with Ctrl+C as soon as alert was confirmed.

As for now, I don't get it, but will play more with this later tonight, now I am still busy on job 😁.

Thank you for the great hint, it could be something from this point.

@aabytt
Copy link
Author

aabytt commented Jan 17, 2024

btw, you can filter the output for particlular service logs with ls-monitor -f
for example ls-monitor -f com.webos.service.btaudiosrc

@aabytt
Copy link
Author

aabytt commented Jan 17, 2024

also I found this thread on openlgtv discord server. possibly it will help you

@stiw47
Copy link

stiw47 commented Jan 17, 2024

Thank you very much for reminder that this discord server exist. I joined long time ago, but forgot for it at all 😅.
Anyway, I found new command for BT connect, which not require sound output switching, and not producin alert. Just by executing this, device is connected and audio output is switched to BT.

luna-send -f -n 1 luna://com.webos.service.btaudiosrc/connect '{"address": "7b:b1:b9:be:82:fe"}'
Thank you!

@be6ana
Copy link

be6ana commented Apr 9, 2024

I did not get subtitles show on HLS stream . On HTTP/Progressive streams subtitles are showing , but not for HLS . With MKV files works too. Is there any another key to set for make it work ?! Thank you for whole your work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment