Skip to content

Commit 303047e

Browse files
v1.2.0: hls support & patched submenus and navigation errors
1 parent 514b51e commit 303047e

7 files changed

Lines changed: 169 additions & 117 deletions

File tree

README.md

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,45 @@
1-
# plugin.video.earthcam plugin for Kodi / XBMC
1+
# plugin.video.earthcam add-on for Kodi / XBMC
22

3-
This plugin version will show you more webcams than any other version on internet!
3+
This add-on version will show you more webcams than any other version on internet!
44

55
EarthCam.com is the premiere network of scenic webcams and offers a complete database of interesting places and views from around the world. EarthCam.com is the worlds favorite webcam network and the EarthCam Network cameras have been seen on top news shows, including CNN Headline News.
66

77
### Installation
88

9-
* [download released zip](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.1.0/plugin.video.earthcam-1.1.0.zip)
9+
* [download released zip](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.2.0/plugin.video.earthcam-1.2.0.zip)
1010
* Kodi/XBMC: System / Add-ons / Install from zip file /
1111
* or Kodi 17: Add-ons / Download / ".." / Install from zip file /
12-
* select [earthcam's zip file](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.1.0/plugin.video.earthcam-1.1.0.zip)
12+
* select [earthcam's zip file](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.2.0/plugin.video.earthcam-1.2.0.zip)
1313
* Note that Kodi will complain about installing from "Unknown sources": in this case, activate this option, and repeat the installation steps.
1414

15+
From version 1.2.0 on, this add-on can play [HLS streams](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), and this mode is more stable than [RTMP](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol).
16+
Please follow **Enable HLS playing** instructions to try it.
17+
1518
### Note for Kodi 17 (Krypton)
1619

1720
* Now, it is necessary to activate the "RTMP input stream": Add-ons / My Add-ons / VideoPlayer InputStream / RTMP Input / Enable
1821

19-
If after enabling the "RTMP input stream" no camera is shown (please, note that some links may not be active: try some USA cams first), the RTMP library may not be functioning - in this case you can **try** these **advanced steps**:
22+
If after enabling the "RTMP input stream" no camera is shown (please, note that some links may not be active: try some USA cams first), the RTMP library may not be functioning - in this case you can try **Install inputstream.rtmp add-on** instructions,
23+
**OR** try **Enable HLS playing** instructions.
2024

21-
Steps to install an **inputstream.rtmp** plugin from [this repo](https://github.com/kodinerds/binary-repo) in order to activate [rtmp videos](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) for Kodi. That repo supports RPi2, Odroid-C2 (deprecated), Windows and Mac OS X.
25+
##### Install **inputstream.rtmp** add-on
26+
Steps to install an **inputstream.rtmp** add-on from [kodinerds repo](https://github.com/kodinerds/binary-repo) in order to activate [rtmp videos](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) for Kodi. That repo supports RPi2 (compatible with RPi3), Odroid-C2 (deprecated), Windows and Mac OS X.
2227

2328
* Download the appropriate *repository.kodinerds_X.zip* zip file for your platform [from here](https://github.com/kodinerds/binary-repo).
2429
* Install this repository on Kodi: Add-ons / Download / .. / Install from zip file / *and select kodiners' zip file*. Previously, "Unknown Sources" must have been activated on: Settings / System / Add-ons / Unknown sources
2530
* Install *inputstream.rtmp* add-on: Add-ons / Download / .. / Install from repository / kodinerds / VideoPlayer InputStream / RTMP Input
26-
* and then, install *plugin.video.earthcam*: Add-ons / Download / .. / Install from zip file / select [earthcam's zip file](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.1.0/plugin.video.earthcam-1.1.0.zip).
31+
* and then, install *plugin.video.earthcam*: Add-ons / Download / .. / Install from zip file / select [earthcam's zip file](https://github.com/idleloop-github/xbmc-earthcam/releases/download/v1.2.0/plugin.video.earthcam-1.2.0.zip).
32+
33+
##### Enable HLS playing
34+
From version 1.2.0 on, this add-on can play [HLS streams](https://en.wikipedia.org/wiki/HTTP_Live_Streaming).
35+
In order to activate this functionality you have to both activate it in this add-on's configuration,
36+
and also install (if necessary) and enable the add-on **InputStream Adaptative** (or another add-on capable of playing HLS - for example [awaiters1 releases](https://github.com/awaters1/inputstream.hls/releases)).
37+
38+
* Configure earthcam add-on: Add-ons / Video add-ons / Earthcam / right click / Settings / Enable HLS instead of RMP : activate
39+
* activate "InputStream Adaptative": Add-ons / My Add-ons / VideoPlayer InputStream / InputStream Adaptative / Enable
40+
* Also, configure it to be able to open HD streams: Add-ons / My Add-ons / VideoPlayer InputStream / InputStream Adaptative / Configure / Max. Resolution general decoder: Max [Ok]
41+
42+
* Now check that you can open some cams. If that is not the case, simply deactivate HLS again: Add-ons / Video add-ons / Earthcam / right click / Settings / Enable HLS instead of RMP : deactivate
2743

2844
### Changes
2945

addon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
22
<addon id="plugin.video.earthcam"
33
name="EarthCam"
4-
version="1.1.0"
4+
version="1.2.0"
55
provider-name="idleloop, (forked from xbmchub.com)">
66
<requires>
77
<import addon="xbmc.python" version="2.1.0"/>

changelog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
v1.2.0
2+
(2017, Sept)
3+
added HLS support: enable it in add-on's configuration if no cam is shown.
4+
patched some errors getting submenus and navigating
5+
16
v1.1.0
27
(2017, Sept)
38
patched for new earthcam web site

channel.py

Lines changed: 77 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
DEBUG = False
2424
if (config.get_setting("debug") == 'true'):
2525
DEBUG=True
26+
HLS = True
27+
if (config.get_setting("hls") == 'false'):
28+
HLS=False
2629
URL = 'https://www.earthcam.com/'
2730
USA_PREFIX_PATCH = 'search/adv_search.php?restrict=1&country[]=United%20States'
2831
WORLDWIDE_PREFIX_PATCH = 'search/adv_search.php?restrict=1&country[]='
@@ -41,11 +44,11 @@ def mainlist(item):
4144
itemlist.append( Item(action="usa", title="USA" , url=URL + USA_PREFIX_PATCH + EARTHCAM_NAVIGATION_LINK_END ) )
4245
return itemlist
4346

44-
def _get_tree(url, just_get = False):
47+
def _get_tree(url, just_get_content = False):
4548

4649
html = scrapertools.cache_page(url)
4750

48-
if just_get == True: return html
51+
if just_get_content == True: return html
4952

5053
try:
5154
tree = BeautifulSoup(html, convertEntities='html')
@@ -58,13 +61,13 @@ def _get_tree(url, just_get = False):
5861
def worldwide(item):
5962
logger.info("[channel.py] worldwide")
6063
itemlist = []
61-
bStopNavigation = False
64+
#bStopNavigation = False
6265

6366
if (DEBUG): logger.info("url=" + item.url)
6467

6568
tree = _get_tree( item.url )
6669

67-
divs = tree.findAll('div', {'class': re.compile(r'.*col-xs-.+result_column_[AB].*')})
70+
divs = tree.findAll('div', {'class': re.compile(r'.*col\-xs\-.+result_column_[AB].*')})
6871

6972
(title, thumbnail, url, location, plot) = ('', '', '', '', '')
7073

@@ -79,8 +82,9 @@ def worldwide(item):
7982
url = div.find('a', {'class': 'camTitle'})['href']
8083
# discard (almost all) the external links:
8184
if not re.search( r'(//www.earthcam.com/|//(www.)?youtube.com/)', url ):
82-
bStopNavigation = True
83-
break
85+
#bStopNavigation = True
86+
#break
87+
pass
8488
title = div.find('a', {'class': 'camTitle'}).span.string.replace('EarthCam: ', '')
8589
location = div.find('div', {'class': 'cam_location'}).string
8690
plot = div.find('div', {'class': 'cam_description'}).string
@@ -96,16 +100,16 @@ def worldwide(item):
96100
links = tree.find('div', {'id': 'pagination_bottom'}).findAll('a')
97101
logger.info(str(links))
98102
# next page
99-
if bStopNavigation == False or (bStopNavigation == True and len(itemlist)>0):
100-
link = links[-1]
101-
if re.search(r'^Next', link.text):
102-
url = link['href']
103-
# Unfortunately, until BeautifulSoup 4.2.1 there're problems with double ampersands, so:
104-
url = URL + USA_PREFIX_PATCH + url[1:]
105-
logger.info(url)
106-
item=Item(action="worldwide", title='Next >>' , url=url, thumbnail='',
107-
fanart='', plot='' )
108-
itemlist.append( item )
103+
#if bStopNavigation == False or (bStopNavigation == True and len(itemlist)>0):
104+
link = links[-1]
105+
if re.search(r'^Next', link.text):
106+
url = link['href']
107+
# Unfortunately, until BeautifulSoup 4.2.1 there're problems with double ampersands, so:
108+
url = URL + USA_PREFIX_PATCH + url[1:]
109+
logger.info(url)
110+
item=Item(action="worldwide", title='Next >>' , url=url, thumbnail='',
111+
fanart='', plot='' )
112+
itemlist.append( item )
109113
except:
110114
pass
111115

@@ -114,7 +118,7 @@ def worldwide(item):
114118
def usa(item):
115119
logger.info("[channel.py] usa")
116120
itemlist = []
117-
bStopNavigation = False
121+
#bStopNavigation = False
118122

119123
if (DEBUG): logger.info("url=" + item.url)
120124

@@ -135,8 +139,9 @@ def usa(item):
135139
url = div.find('a', {'class': 'camTitle'})['href']
136140
# discard (almost all) the external links:
137141
if not re.search( r'(//www.earthcam.com/|//(www.)?youtube.com/)', url ):
138-
bStopNavigation = True
139-
break
142+
#bStopNavigation = True
143+
#break
144+
pass
140145
title = div.find('a', {'class': 'camTitle'}).span.string.replace('EarthCam: ', '')
141146
location = div.find('div', {'class': 'cam_location'}).string
142147
plot = div.find('div', {'class': 'cam_description'}).string
@@ -152,16 +157,16 @@ def usa(item):
152157
links = tree.find('div', {'id': 'pagination_bottom'}).findAll('a')
153158
logger.info(str(links))
154159
# next page
155-
if bStopNavigation == False or (bStopNavigation == True and len(itemlist)>0):
156-
link = links[-1]
157-
if re.search(r'^Next', link.text):
158-
url = link['href']
159-
# Unfortunately, until BeautifulSoup 4.2.1 there're problems with double ampersands, so:
160-
url = URL + USA_PREFIX_PATCH + url[1:]
161-
logger.info(url)
162-
item=Item(action="usa", title='Next >>' , url=url, thumbnail='',
163-
fanart='', plot='' )
164-
itemlist.append( item )
160+
#if bStopNavigation == False or (bStopNavigation == True and len(itemlist)>0):
161+
link = links[-1]
162+
if re.search(r'^Next', link.text):
163+
url = link['href']
164+
# Unfortunately, until BeautifulSoup 4.2.1 there're problems with double ampersands, so:
165+
url = URL + USA_PREFIX_PATCH + url[1:]
166+
logger.info(url)
167+
item=Item(action="usa", title='Next >>' , url=url, thumbnail='',
168+
fanart='', plot='' )
169+
itemlist.append( item )
165170
except:
166171
pass
167172

@@ -175,7 +180,7 @@ def cams(item):
175180

176181
#tree = _get_tree( item.url )
177182
# Ops... some earthcam's wrong html code here mangles BeautifulSoup tree :-(
178-
html = _get_tree( item.url, just_get=True )
183+
html = _get_tree( item.url, just_get_content=True )
179184
html = html.replace(' ; id=', ' id=')
180185
try:
181186
tree = BeautifulSoup(html, convertEntities='html')
@@ -253,7 +258,7 @@ def previous_play(item, just_check=False):
253258

254259
#http://www.earthcam.com/usa/newyork/timessquare/?cam=tsstreet
255260
#if "?cam=" in item.url:
256-
video_url=""
261+
#video_url=""
257262
#try:
258263
# # Extract cam_id
259264
# cam_id = item.url.split("?")[1].split("=")[1]
@@ -283,44 +288,54 @@ def previous_play(item, just_check=False):
283288
if (DEBUG): logger.info("liveon="+liveon)
284289
if liveon!="disabled":
285290
###video_url = cam_data[cam_id]["worldtour_path"]
286-
video_url
291+
video_url = ''
287292
try:
288-
if "worldtour_path" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4|\.jpg|\.png)$', cam_data[cam_id]["worldtour_path"] ):
289-
video_url = cam_data[cam_id]["worldtour_path"]
290-
elif "livestreamingpath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["livestreamingpath"] ):
291-
video_url = cam_data[cam_id]["streamingdomain"] + cam_data[cam_id]["livestreamingpath"]
292-
elif "timelapsepath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["timelapsepath"] ):
293-
video_url = cam_data[cam_id]["timelapsedomain"] + cam_data[cam_id]["timelapsepath"]
294-
elif "archivepath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["archivepath"] ):
295-
video_url = cam_data[cam_id]["archivedomain"] + cam_data[cam_id]["archivepath"]
293+
if (HLS):
294+
if "html5_streamingdomain" in cam_data[cam_id]:
295+
video_url = 'http:' + cam_data[cam_id]["html5_streamingdomain"]
296+
if "html5_streampath" in cam_data[cam_id] and re.search( r'(\.m3u8)$', cam_data[cam_id]["html5_streampath"] ):
297+
video_url = video_url + cam_data[cam_id]["html5_streampath"]
298+
if (DEBUG): logger.info("html5_stream="+video_url)
299+
else:
300+
continue
296301
else:
297-
continue
302+
if "worldtour_path" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4|\.jpg|\.png)$', cam_data[cam_id]["worldtour_path"] ):
303+
video_url = cam_data[cam_id]["worldtour_path"]
304+
elif "livestreamingpath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["livestreamingpath"] ):
305+
video_url = cam_data[cam_id]["streamingdomain"] + cam_data[cam_id]["livestreamingpath"]
306+
elif "timelapsepath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["timelapsepath"] ):
307+
video_url = cam_data[cam_id]["timelapsedomain"] + cam_data[cam_id]["timelapsepath"]
308+
elif "archivepath" in cam_data[cam_id] and re.search( r'(\.flv|\.mp4)$', cam_data[cam_id]["archivepath"] ):
309+
video_url = cam_data[cam_id]["archivedomain"] + cam_data[cam_id]["archivepath"]
310+
else:
311+
continue
298312
#video_url=re.sub(r'(?<!:)//','/',video_url)
299313
url = calculate_url(video_url)
300-
item=Item(action="play", url=url,
301-
folder=False)
302314
try:
303-
item.title=cam_data[cam_id]["title"]
315+
title=cam_data[cam_id]["title"]
304316
except Exception, e:
305-
item.title=str(cam_id)
317+
title=str(cam_id)
306318
try:
307-
item.fanart=cam_data[cam_id]["offlineimage"]
319+
fanart=cam_data[cam_id]["offlineimage"]
308320
except Exception, e:
309-
logger.info("[channel.py] [play] ERROR: no fanart")
321+
fanart=''
322+
if (DEBUG): logger.info("[channel.py] [play] ERROR: no fanart")
310323
try:
311-
item.thumbnail=cam_data[cam_id]["thumbimage"]
324+
thumbnail=cam_data[cam_id]["thumbimage"]
312325
except Exception, e:
313-
logger.info("[channel.py] [play] ERROR: no thumbnail")
326+
thumbnail=''
327+
if (DEBUG): logger.info("[channel.py] [play] ERROR: no thumbnail")
314328
try:
315-
item.plot = re.sub(r'</?span[^>]*>', '',
329+
plot = re.sub(r'</?span[^>]*>', '',
316330
cam_data[cam_id]["description"].replace('+', ' '),
317331
flags=re.IGNORECASE )
318-
item.plot = re.sub(r'<[^>]+>', "\n", item.plot)
332+
plot = re.sub(r'<[^>]+>', "\n", plot)
319333
except Exception, e:
320-
logger.info("[channel.py] [play] ERROR: no plot")
321-
itemlist.append( item )
334+
plot=''
335+
if (DEBUG): logger.info("[channel.py] [play] ERROR: no plot")
336+
itemlist.append( Item(action="play", url=url, thumbnail=thumbnail, title=title, fanart=fanart, plot=plot) )
322337
except Exception, e:
323-
logger.info("[channel.py] [play] ERROR:"+url)
338+
if (DEBUG): logger.info("[channel.py] [play] ERROR:"+url)
324339

325340
return itemlist
326341

@@ -329,7 +344,7 @@ def play(item):
329344
if re.search( r'//(www.)?youtube.com/', item.url ):
330345
video_id = re.sub('.+?=', '', item.url)
331346
xbmc.executebuiltin('PlayMedia(plugin://plugin.video.youtube/play/?video_id=' + video_id + ')')
332-
elif re.search( r'(\.flv|\.mp4|\.jpg|\.png)$', item.url ) or item.url.startswith("rtmp"):
347+
elif re.search( r'(\.flv|\.mp4|\.jpg|\.png|\.m3u8)$', item.url ) or item.url.startswith("rtmp"):
333348
itemlist.append( item )
334349
else: # for backward compatitbility with v1.0.7 favorites
335350
itemlist=previous_play( item )
@@ -344,6 +359,12 @@ def calculate_url(video_url):
344359
# rtmp://video2.earthcam.com/ app=fecnetwork swfUrl=http://www.earthcam.com/swf/cam_player_v2/ecnPlayer.swf playpath=fridaysHD1.flv live=true timeout=180
345360
if video_url.lower().endswith(".jpg") or video_url.lower().endswith(".png"):
346361
url = video_url
362+
elif video_url.lower().endswith(".m3u8"):
363+
try:
364+
m3u8_content = _get_tree(video_url, just_get_content = True)
365+
url = video_url.replace( 'playlist', re.search(r'^([^#].+)\.m3u8$', m3u8_content, re.MULTILINE).group(1) )
366+
except:
367+
url=''
347368
elif video_url.lower().startswith("http://") or video_url.lower().startswith("https://") or video_url.lower().endswith(".mp4"):
348369
url = video_url
349370
else:
@@ -353,7 +374,7 @@ def calculate_url(video_url):
353374
playpath = scrapertools.get_match(video_url,"rtmp\://[^\/]+/[a-z]+/(.+\.flv)")
354375
swfurl = "http://www.earthcam.com/swf/cam_player_v2/ecnPlayer.swf"
355376
url=rtmp_url + " app=" + app + " swfUrl=" + swfurl + " playpath=" + playpath + " live=true timeout=180"
356-
if (DEBUG): logger.info("url="+url)
377+
if (DEBUG): logger.info("calculated_url="+url)
357378
return url
358379

359380

0 commit comments

Comments
 (0)