Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
gcc -O2 mlb.c utils.c output.c -lm -lcurl -lcrypto -lconfig -o mlbhls
mlb.c: In function ‘mlb_refresh_playlists’:
mlb.c:169:22: warning: embedded ‘\0’ in format [-Wformat-contains-nul]
sprintf(tmp_url, "%s%s\0", master->base_url, master->streams[i].base_url);
^
mlb.c: In function ‘mlb_process_streams’:
mlb.c:791:10: warning: implicit declaration of function ‘strptime’ [-Wimplicit-function-declaration]
if (strptime(tmp, MLB_HLS_TIME_FORMAT, &tm) != 0)
^
mlb.c: In function ‘mlb_hls_get_and_decrypt’:
mlb.c:859:24: warning: embedded ‘\0’ in format [-Wformat-contains-nul]
sprintf(content_url, "%s%s%s\0", master->base_url, stream->base_url_media, url);
^
mlb.c: In function ‘main’:
mlb.c:1362:43: warning: embedded ‘\0’ in format [-Wformat-contains-nul]
sprintf(master->cmd_params, "%s -cache %d %s\0", master->args->launch_cmd, 4*(master->decrypted_size/(p.stream->seg_time * master->decrypte
^
/usr/bin/ld: /tmp/ccl4PJXi.o: undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'mlb' failed
make: *** [mlb] Error 1
Then starts dumping trash to the terminal (the stream?).
Running it with sudo privs does work, though, and will dump a file.... but this file is unplayable despite being 1.5+ GB in size. Last few error messages are:
[MLB] Get (4870): 02/14/34.ts (bw: 800000, time: 0.21s) [Avg. D/L Rate of last 3 chunks: 27.29 Mbps]
[MLB] Get (4872): 02/14/39.ts (bw: 800000, time: 0.21s) [Avg. D/L Rate of last 3 chunks: 26.16 Mbps]
[MLB] Get (4874): 02/14/44.ts (bw: 800000, time: 0.19s) [Avg. D/L Rate of last 3 chunks: 29.09 Mbps]
[MLB] Get (4876): 02/14/49.ts (bw: 800000, time: 0.20s) [Avg. D/L Rate of last 3 chunks: 26.30 Mbps]
[MLB] Skipping Playlist: 1800K/1800_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Skipping Playlist: 800K/800_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Skipping Playlist: 1200K/1200_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Skipping Playlist: 2500K/2500_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Skipping Playlist: 3500K/3500_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Skipping Playlist: 5000K/5000_complete-trimmed.m3u8 (reason: End of Playlist)
[MLB] Stream thread exiting
Calling mlbhls without the -F flag will result in a file that is playable but is just the end of the stream. Obviously there is a stream time finding issue...
Snippets of the Kodi plugin that might help replace mlbhls:
Code:
def createFullGameStream(stream_url, media_auth, media_state):
#SD (800 kbps)|SD (1600 kbps)|HD (3000 kbps)|HD (5000 kbps)
bandwidth = ''
bandwidth = find(QUALITY,'(',' kbps)')
if QUALITY == 'Always Ask':
bandwidth = getStreamQuality(stream_url)
#Only set bandwidth if it's explicitly set
if bandwidth != '':
if media_state == 'MEDIA_ARCHIVE':
#ARCHIVE
#stream_url = stream_url.replace(MASTER_FILE_TYPE, bandwidth+'K/'+bandwidth+'_complete_fwv2-trimmed.m3u8')
stream_url = stream_url.replace(MASTER_FILE_TYPE, bandwidth+'K/'+bandwidth+'_complete-trimmed.m3u8')
elif media_state == 'MEDIA_ON':
#LIVE
#stream_url = stream_url.replace(MASTER_FILE_TYPE, bandwidth+'K/'+bandwidth+'_slide_fwv2.m3u8')
stream_url = stream_url.replace(MASTER_FILE_TYPE, bandwidth+'K/'+bandwidth+'_complete.m3u8')
#CDN
akc_url = 'akc.mlb.com'
l3c_url = 'l3c.mlb.com'
if CDN == 'Akamai' and akc_url not in stream_url:
stream_url = stream_url.replace(l3c_url,akc_url)
elif CDN == 'Level 3' and l3c_url not in stream_url:
stream_url = stream_url.replace(akc_url,l3c_url)
#stream_url = stream_url + '|User-Agent='+UA_IPAD+'&Cookie='+media_auth
stream_url = stream_url + '|User-Agent='+UA_PS4+'&Cookie='+media_auth
return stream_url
and
Code:
def fetchStream(content_id,event_id,playback_scenario):
stream_url = ''
media_auth = ''
identity_point_id = ''
fingerprint = ''
expired_cookies = True
try:
cj = cookielib.LWPCookieJar(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'))
cj.load(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'),ignore_discard=True)
#Check if cookies have expired
at_least_one_expired = False
num_cookies = 0
for cookie in cj:
num_cookies += 1
if cookie.is_expired():
at_least_one_expired = True
break
if not at_least_one_expired:
expired_cookies = False
except:
pass
if expired_cookies or num_cookies == 0 or USERNAME != OLD_USERNAME or PASSWORD != OLD_PASSWORD:
#Remove cookie file
cookie_file = xbmc.translatePath(os.path.join(ADDON_PATH_PROFILE+'cookies.lwp'))
try:
os.remove(cookie_file)
except:
pass
login()
cj = cookielib.LWPCookieJar(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'))
cj.load(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'),ignore_discard=True)
for cookie in cj:
if cookie.name == "ipid":
identity_point_id = cookie.value
elif cookie.name == "fprt":
fingerprint = cookie.value
if identity_point_id == '' or fingerprint == '':
return stream_url, media_auth
session_key = getSessionKey(content_id,event_id,identity_point_id,fingerprint)
#Reload Cookies
cj = cookielib.LWPCookieJar(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'))
cj.load(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'),ignore_discard=True)
if PROXY_ENABLED != 'true':
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
else:
proxy_url = 'http://'+PROXY_SERVER+':'+PROXY_PORT
proxy_support = urllib2.ProxyHandler({ 'http': proxy_url, 'https': proxy_url })
if PROXY_USER != '' and PROXY_PWD != '':
auth_handler = urllib2.ProxyBasicAuthHandler()
auth_handler.add_password(None, proxy_url, PROXY_USER, PROXY_PWD)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), proxy_support, auth_handler)
else:
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), proxy_support)
urllib2.install_opener(opener)
if session_key == '':
return stream_url, media_auth
elif session_key == 'blackout':
msg = "The game you are trying to access is not currently available due to local or national blackout restrictions.\n Full game archives will be available 48 hours after completion of this game."
dialog = xbmcgui.Dialog()
ok = dialog.ok('Game Blacked Out', msg)
return stream_url, media_auth
url = 'https://mlb-ws-mf.media.mlb.com/pubajaxws/bamrest/MediaService2_0/op-findUserVerifiedEvent/v-2.3'
url = url + '?identityPointId='+identity_point_id
url = url + '&fingerprint='+fingerprint
url = url + '&contentId='+content_id
url = url + '&eventId='+event_id
url = url + '&playbackScenario='+playback_scenario
url = url + '&subject=LIVE_EVENT_COVERAGE'
url = url + '&sessionKey='+urllib.quote_plus(session_key)
url = url + '&platform=PS4'
url = url + '&format=json'
req = urllib2.Request(url)
req.add_header("Accept", "*/*")
req.add_header("Accept-Encoding", "deflate")
req.add_header("Accept-Language", "en-US,en;q=0.8")
req.add_header("Connection", "keep-alive")
req.add_header("User-Agent", UA_PS4)
response = opener.open(req)
json_source = json.load(response)
response.close()
if json_source['status_code'] == 1:
uv_media_item = json_source['user_verified_event'][0]['user_verified_content'][0]['user_verified_media_item'][0]
if 'BLACKOUT' in str(uv_media_item ['blackout_status']).upper():
msg = "We're sorry. We have determined that you are blacked out of watching the game you selected due to Major League Baseball exclusivities."
#try:
if str(uv_media_item ['media_item']['state']).upper() == 'MEDIA_ARCHIVE':
#cc_url = str(json_source['user_verified_event'][0]['user_verified_content'][0]['domain_specific_attributes'][3]['value'])
for attribute in json_source['user_verified_event'][0]['user_verified_content'][0]['domain_specific_attributes']:
if str(attribute['name']).lower() == 'inning_index_location_xml':
inning_xml_url = str(attribute['value'])
#inning_xml_url = "http://mlb.mlb.com/mlb/mmls2016/447002.xml"
blackout_lift_min, blackout_lift_time = getBlackoutLiftTime(inning_xml_url)
msg = msg + " This blackout will expire in "+str(blackout_lift_min)+" minutes at approximately "+str(blackout_lift_time)+"."
break
dialog = xbmcgui.Dialog()
ok = dialog.ok('Game Blacked Out', msg)
sys.exit()
xbmc.executebuiltin('Dialog.Close(all,true)')
elif str(uv_media_item ['auth_status']) == 'NotAuthorizedStatus':
msg = "You do not have an active MLB.TV premium subscription. If you are using a Single Team or Free subscription please check this is enabled in the addon settings."
dialog = xbmcgui.Dialog()
ok = dialog.ok('Account Not Authorized', msg)
sys.exit()
xbmc.executebuiltin('Dialog.Close(all,true)')
else:
stream_url = uv_media_item ['url']
#Find subtitles
'''
for item in json_source['user_verified_event'][0]['user_verified_content'][0]['domain_specific_attributes']:
if item['name'] == 'closed_captions_location_ttml':
subtitles_url = item['value']
convertSubtitles(subtitles_url)
'''
session_key = json_source['session_key']
#Update Session Key
settings.setSetting(id='session_key', value=session_key)
else:
msg = json_source['status_message']
dialog = xbmcgui.Dialog()
ok = dialog.ok('Error Fetching Stream', msg)
for cookie in cj:
if cookie.name == "mediaAuth":
media_auth = "mediaAuth="+cookie.value
settings.setSetting(id='media_auth', value=media_auth)
cj.save(ignore_discard=True)
return stream_url, media_auth
and
Code:
def getSessionKey(content_id,event_id,identity_point_id,fingerprint):
#session_key = ''
session_key = str(settings.getSetting(id="session_key"))
if session_key == '':
cj = cookielib.LWPCookieJar(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'))
cj.load(os.path.join(ADDON_PATH_PROFILE, 'cookies.lwp'),ignore_discard=True)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
epoch_time_now = str(int(round(time.time()*1000)))
url = 'https://mlb-ws-mf.media.mlb.com/pubajaxws/bamrest/MediaService2_0/op-findUserVerifiedEvent/v-2.3'
url = url + '?identityPointId='+identity_point_id
url = url + '&fingerprint='+fingerprint
url = url + '&eventId='+event_id
url = url + '&subject=LIVE_EVENT_COVERAGE'
url = url + '&platform=WIN8'
url = url + '&frameworkURL=https://mlb-ws-mf.media.mlb.com&frameworkEndPoint=/pubajaxws/bamrest/MediaService2_0/op-findUserVerifiedEvent/v-2.3'
url = url + '&_='+epoch_time_now
req = urllib2.Request(url)
req.add_header("Accept", "*/*")
req.add_header("Accept-Encoding", "deflate")
req.add_header("Accept-Language", "en-US,en;q=0.8")
req.add_header("Connection", "keep-alive")
req.add_header("User-Agent", UA_PC)
req.add_header("Origin", "http://m.mlb.com")
req.add_header("Referer", "http://m.mlb.com/tv/e"+event_id+"/v"+content_id+"/?&media_type=video&clickOrigin=Media Grid&team=mlb&forwardUrl=http://m.mlb.com/tv/e"+event_id+"/v"+content_id+"/?&media_type=video&clickOrigin=Media%20Grid&team=mlb&template=mp5default&flowId=registration.dynaindex&mediaTypeTemplate=video")
response = opener.open(req)
xml_data = response.read()
response.close()
session_key = find(xml_data,'<session-key>','</session-key>')
settings.setSetting(id='session_key', value=session_key)
'''
if json_source['status_code'] == 1:
if json_source['user_verified_event'][0]['user_verified_content'][0]['user_verified_media_item'][0]['blackout_status']['status'] == 'BlackedOutStatus':
msg = "You do not have access to view this content. To watch live games and learn more about blackout restrictions, please visit NHL.TV"
session_key = 'blackout'
else:
session_key = str(json_source['session_key'])
settings.setSetting(id='session_key', value=session_key)
else:
msg = json_source['status_message']
dialog = xbmcgui.Dialog()
ok = dialog.ok('Error Fetching Stream', msg)
'''
return session_key
Sorry I keep flooding the thread, but want to document as much as possible. It seems like the start time of the game is the issue. mlbhls is working fine in downloading the files, they're just started at the wrong time so the file is corrupt.
Is it this function that is causing the issues and offset problems?
Code:
def getStartOfGame(self,listing,cfg):
start_time = 0
try:
innings = self.parseInningsXml(listing[2][0][3],
cfg.get('use_nexdef'))
except:
return None
if listing[5] in ('I', 'D', 'NB' ) and start_time == 0:
if cfg.get('live_from_start') and cfg.get('use_nexdef'):
if innings is not None:
start_time = innings[0]
else:
if cfg.get('use_nexdef'):
if innings is not None:
start_time = innings[0]
# hack to make sure mlbhls can start at the correct
# timestamp - add five seconds to published time
#d=datetime.datetime.strptime(start_time, "%H:%M:%S")
#t=datetime.timedelta(seconds=5)
#n=d+t
#start_time=n.strftime("%H:%M:%S")
else:
start_time=listing[8]
return start_time
I uncommented the offset code and ran it, but that didn't help. For this KCA/CLE game on 5/26 the mlbhls output gives me a playable file that has the "Thanks for watching the game" banner flying if I use anything before -F 22:59:00. When I use 23:00:00 or above, it dumps an unintelligible file that mplayer cannot read.
The tfs_zulu for this file is 23:11:27 (cannot tell from daftcat's code how exactly this time is pulled since mlbplayer will spit out 22:59:55 without the offset code and 23:00:00 with it).
Ah ha! So finally I see the TS files "directories" really just correspond to time codes. And for some reason mlbhls is screwing up the offset. When it says Get (8), Get (10) there's clearly stuff behind it that's not being captured.
See how I tried a time stamp in the past for this stream and it worked:
Code:
[MLB] Reading cfg file: mlb.cfg
[MLB] Output file: test3.mp4
[MLB] Segment Avg. Count: 3
[MLB] Max Bandwidth: 0 (bps)
[MLB] Min Bandwidth: 0 (bps)
[MLB] Bandwidth Locking: 1
[MLB] Fetching Master URL: http://mlblive-akc.mlb.com/ls01/mlbam/2017/05/26/MLB_GAME_VIDEO_KCACLE_HOME_20170526_1494965299550/master_wired60.m3u8
[MLB] Current Priority: 5 (bw: 5000000)
[MLB] Master URL: http://mlblive-akc.mlb.com/ls01/mlbam/2017/05/26/MLB_GAME_VIDEO_KCACLE_HOME_20170526_1494965299550/master_wired60.m3u8
[MLB] Base URL: http://mlblive-akc.mlb.com/ls01/mlbam/2017/05/26/MLB_GAME_VIDEO_KCACLE_HOME_20170526_1494965299550/
[MLB] Decryption Key: a1e4a3ea33cbb512a9448e1836d4a179
[MLB] Params: playback=HTTP_CLOUD_WIRED_WEB&contentId=1393700883&appAccountName=mlb&eventId=14-490820-2017-05-26&ipid=78557067&sessionKey=rnL%2BALLN76eNxgJ7a9gLogVSqmA%3D
[MLB] Stream #0 - rate: 1800000 - path: [1800K/] - playlist: 1800K/1800_complete-trimmed.m3u8
[MLB] Stream #1 - rate: 800000 - path: [800K/] - playlist: 800K/800_complete-trimmed.m3u8
[MLB] Stream #2 - rate: 1200000 - path: [1200K/] - playlist: 1200K/1200_complete-trimmed.m3u8
[MLB] Stream #3 - rate: 2500000 - path: [2500K/] - playlist: 2500K/2500_complete-trimmed.m3u8
[MLB] Stream #4 - rate: 3500000 - path: [3500K/] - playlist: 3500K/3500_complete-trimmed.m3u8
[MLB] Stream #5 - rate: 5000000 - path: [5000K/] - playlist: 5000K/5000_complete-trimmed.m3u8
[MLB] Playlist refresh time: 12 (s)
[MLB] Playlist start: 82792 (specified start: 82793)
[MLB] END OF PLAYLIST! (rate: 1800000)
[MLB] Setting stream start time to (epoch): 1495864792
[MLB] ##### start_from_playlist: 1 -- 1 -- 4877
[MLB] END OF PLAYLIST! (rate: 800000)
[MLB] END OF PLAYLIST! (rate: 1200000)
[MLB] END OF PLAYLIST! (rate: 2500000)
[MLB] END OF PLAYLIST! (rate: 3500000)
[MLB] END OF PLAYLIST! (rate: 5000000)
[MLB] Get (8): 22/59/52.ts (bw: 5000000, time: 0.83s) [Avg. D/L Rate of last 3 chunks: 32.39 Mbps]
[MLB] Get (10): 22/59/57.ts (bw: 5000000, time: 0.96s) [Avg. D/L Rate of last 3 chunks: 27.61 Mbps]
[MLB] Get (12): 23/00/02.ts (bw: 5000000, time: 0.74s) [Avg. D/L Rate of last 3 chunks: 41.71 Mbps]
[MLB] Get (14): 23/00/07.ts (bw: 5000000, time: 0.58s) [Avg. D/L Rate of last 3 chunks: 47.15 Mbps]
[MLB] Get (16): 23/00/12.ts (bw: 5000000, time: 0.48s) [Avg. D/L Rate of last 3 chunks: 47.61 Mbps]
[MLB] Get (18): 23/00/17.ts (bw: 5000000, time: 0.65s) [Avg. D/L Rate of last 3 chunks: 47.40 Mbps]
^C
mlbviewer@mlbviewer:~/mlbtv-hls-nexdef$ sudo wget http://mlblive-akc.mlb.com/ls01/mlbam/2017/05/26/MLB_GAME_VIDEO_KCACLE_HOME_20170526_1494965299550/5000K/22/59/47.ts
--2017-05-27 02:06:13-- http://mlblive-akc.mlb.com/ls01/mlbam/2017/05/26/MLB_GAME_VIDEO_KCACLE_HOME_20170526_1494965299550/5000K/22/59/47.ts
Resolving mlblive-akc.mlb.com (mlblive-akc.mlb.com)... 23.204.103.105, 23.204.103.137, 2001:559:19:1800::1720:2e32, ...
Connecting to mlblive-akc.mlb.com (mlblive-akc.mlb.com)|23.204.103.105|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3473120 (3.3M) [video/mpeg]
Saving to: ‘47.ts’
47.ts 100%[============================================================================================>] 3.31M 3.86MB/s in 0.9s
2017-05-27 02:06:14 (3.86 MB/s) - ‘47.ts’ saved [3473120/3473120]
The -F option is needed to find the correct start of game and start of innings.
The experimental branch of mlbhls is needed for the -F argument.
I'm sure you can find your way to hack that option out of my code. But I'm also certain your experience with mlbviewer will be better if you keep it. Search this thread for "F patch" or "mlbhls experimental branch" if you still need assistance finding the correct version of mlbhls.
Hi all, I've recently installed the latest version of the MLB viewer. I've gone through the requirements page and I've installed all of the dependiencies. When I try to run the script I get:
python2 mlbviewer.py
Traceback (most recent call last):
File "mlbviewer.py", line 1395, in <module>
curses.wrapper(mainloop, mycfg, mykeys)
File "/usr/lib/python2.7/curses/wrapper.py", line 43, in wrapper
return func(stdscr, *args, **kwds)
File "mlbviewer.py", line 87, in mainloop
log = open(LOGFILE, "a")
IOError: [Errno 13] Permission denied: '/home/tony/.mlb/log'
I'm not really sure what's going on here. thanks for the help.
Hi all, I've recently installed the latest version of the MLB viewer. I've gone through the requirements page and I've installed all of the dependiencies. When I try to run the script I get:
python2 mlbviewer.py
Traceback (most recent call last):
File "mlbviewer.py", line 1395, in <module>
curses.wrapper(mainloop, mycfg, mykeys)
File "/usr/lib/python2.7/curses/wrapper.py", line 43, in wrapper
return func(stdscr, *args, **kwds)
File "mlbviewer.py", line 87, in mainloop
log = open(LOGFILE, "a")
IOError: [Errno 13] Permission denied: '/home/tony/.mlb/log'
I'm not really sure what's going on here. thanks for the help.
Looks like a permission issue like maybe you ran it once as root or sudo and now the log (or directory) is not writable by your user account.
What does "ls -ld /home/tony/.mlb" say? And "ls -l /home/tony/.mlb/log"? Please copy the outputs in a reply before fixing this so I can understand how you got here in the first place.
ERROR: You are not authorized to view this content.
When attempting to watch the World Series game 3:
Code:
ERROR: You are not authorized to view this content.
If you are a basic subscriber, try the home stream.
See /home/peter/.mlb/log for more details.
.mlb/log:
Code:
10/28 16:01 | SUCCESSFUL MEDIA REQUEST: status-code: 1 , event-id = 14-526513-2017-10-27
10/28 16:01 | See /home/peter/.mlb/successful-1.xml for XML response.
10/28 16:01 | Received a notAuthorized status. Response was saved in /home/peter/.mlb/unsuccessful-2.xml.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.