{"action":"created","comment":{"url":"https://api.github.com/repos/kaltura/playkit-js/pulls/comments/196308168","pull_request_review_id":129820938,"id":196308168,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5NjMwODE2OA==","diff_hunk":"@@ -0,0 +1,397 @@\n+import Error from '../error/error'\n+import * as Utils from '../utils/util'\n+import {Parser, StringDecoder} from './text-track-display'\n+import {TrackType} from \"./track-type\";\n+import TextTrack from \"./text-track\";\n+import {CustomEventType, Html5EventType} from \"../event/event-type\";\n+import FakeEvent from \"../event/fake-event\";\n+import getLogger from \"../utils/logger\";\n+import EventManager from \"../event/event-manager\";\n+\n+class ExternalCaptionsHandler {\n+\n+  static SRT_POSTFIX: string = 'srt';\n+  /**\n+   * The player class logger.\n+   * @type {any}\n+   * @static\n+   * @private\n+   */\n+  static _logger: any = getLogger('ExternalCaptionsHandler');\n+  /**\n+   * Index that specifies the last cue that is playing / played in the text track cue array.\n+   * @type {number}\n+   * @private\n+   */\n+  _externalCueIndex: number = 0;\n+  /**\n+   * a callback of the timeupdate, for external captions handler.\n+   * @type {Function}\n+   * @private\n+   */\n+  _handleExternalCaptionsCallback: Function = null;\n+  /**\n+   * the player object.\n+   * @type {Object}\n+   * @private\n+   */\n+  _player: null;\n+  /**\n+   * event manager for the external caption handler\n+   * @type {EventManager}\n+   * @private\n+   */\n+  _eventManager: EventManager = null;\n+\n+  /**\n+   * a map that holds the current cues that are in process. process may be in download or that the cues are being parsed.\n+   * @type {Object} language: promise<*>\n+   * @private\n+   */\n+  _cuesInProcessMap: Object = {};\n+\n+  /**\n+   * constructor\n+   * @param {Object} player - the player object.\n+   */\n+  constructor(player: Object) {\n+    this._player = player;\n+    this._eventManager = new EventManager();\n+    this._addListeners();\n+  }\n+\n+  /**\n+   * adds listeners to the player, so the module will handle them on its own.\n+   * @returns {void}\n+   * @private\n+   */\n+  _addListeners(): void {\n+    this._eventManager.listen(this._player, this._player.Event.SEEKED, (e) => {\n+      this._maybeSetExternalCueIndex(e)\n+    });\n+    this._eventManager.listen(this._player, this._player.Event.TEXT_TRACK_CHANGED, (e) => {\n+      this._handleTextTrackChanged(e)\n+    });\n+  }\n+\n+  /**\n+   * Make a request to download a caption and parse it's content to cues.\n+   * @param {TextTrack} textTrack - download and parse the cues of the text track\n+   * @returns {Promise<any>} - resolves when the request returns and the caption string is parsed to cues.\n+   * @private\n+   */\n+  _getCuesArray(textTrack: TextTrack): Promise<*> {\n+    let cuesPromise = new Promise((resolve, reject) => {\n+      Utils.Http.execute(textTrack.url, {}, 'GET').then(response => {\n+        if ((typeof textTrack.captionsType != 'undefined' && textTrack.captionsType === ExternalCaptionsHandler.SRT_POSTFIX) || this._getFileType(textTrack.url) === ExternalCaptionsHandler.SRT_POSTFIX) {\n+          response = this._convertSrtToVtt(response);\n+        }\n+        this._parseCues(response, resolve);\n+      }).catch(error => {\n+        reject(new Error(Error.Severity.RECOVERABLE, Error.Category.TEXT, Error.Code.HTTP_ERROR, error.payload));\n+      })\n+    });\n+    this._cuesInProcessMap[textTrack.language] = cuesPromise;\n+    return cuesPromise;\n+  }\n+\n+  /**\n+   * this calls the VTTCue parser and parse the .vtt captions string into vttCues objects\n+   * @param {string} vttStr - a string in a .vtt format to parse into VTTCues\n+   * @param {Function} resolve - a resolve function of the calling function.\n+   * @returns {void}\n+   * @private\n+   */\n+  _parseCues(vttStr: string, resolve: Function): void {\n+    const parser = new Parser(window, StringDecoder());\n+    let cues = [];\n+    parser.oncue = cue => {\n+      cues.push(cue);\n+    };\n+    parser.onflush = () => {\n+      ExternalCaptionsHandler._logger.debug('finished parsing external cues');\n+      resolve(cues);\n+    };\n+    parser.parse(vttStr);\n+    parser.flush();\n+  }\n+\n+  /**\n+   * converts a .SRT string into .VTT string\n+   * @param {string} str - a string in a .SRT format\n+   * @returns {string} - a string in a .VTT format\n+   * @private\n+   */\n+  _convertSrtToVtt(str: string): string {\n+    return str.replace(/(\\d\\d:\\d\\d:\\d\\d).(\\d\\d\\d) --> (\\d\\d:\\d\\d:\\d\\d).(\\d\\d\\d)/g, (match, part1, part2, part3, part4) => {\n+      return `${part1},${part2} --> ${part3},${part4}`;\n+    });\n+  }\n+\n+  /**\n+   * resolves with a caption object that contains all the caption data\n+   * start the parsing, creation and addition of the external captions.\n+   * @param {TextTrack} textTrack - create a single caption. when the process ends, the caption is removed from the\n+   * _cuesInProcessMap.\n+   * @returns {Promise<any>} - the caption object with the parsed cues\n+   * @private\n+   */\n+  _createCaption(textTrack: TextTrack): Promise<*> {\n+    return new Promise((resolve) => {\n+      this._getCuesArray(textTrack)\n+        .then(cues => {\n+          textTrack.cues = cues;\n+          this._player.setTextTrackCues(textTrack);\n+          delete this._cuesInProcessMap[textTrack.language];\n+          resolve();\n+        });\n+    });\n+  }\n+\n+  /**\n+   * this function runs on the players text tracks and checks if there is already a text track with the same language\n+   * as the new one.\n+   * @param {TextTrack} textTrack - the text track to check\n+   * @returns {number} - the index of the text track with the same language (if there is any). and -1 if there isn't\n+   * @private\n+   */\n+  _indexOfSameLanguageTrack(textTrack: TextTrack): number {\n+    const trackList = this._player.getVideoElement().textTracks;\n+    let index = -1;\n+    for (let i = 0; i < trackList.length; i++) {\n+      if (trackList[i].language === textTrack.language) {\n+        index = i;\n+        break;\n+      }\n+    }\n+    return index;\n+  }\n+\n+  /**\n+   * getting the file extension\n+   * @param {string} url - the url of the file\n+   * @returns {string} type of the file\n+   * @private\n+   */\n+  _getFileType(url: string): string {\n+    return url.split(/\\#|\\?/)[0].split('.').pop().trim();\n+  }\n+\n+  /**\n+   * callback for the 'timeupdate' event. on each time update this runs and checks if the active text cues array\n+   * was changed.\n+   * @param {TextTrack} track - the text track that that is currently displayed (active)\n+   * @returns {void}\n+   * @private\n+   */\n+  _handleCaptionOnTimeUpdate(track: TextTrack): void {\n+    if (this._player.activeTextCues.length > 0 && this._player.currentTime < this._player.activeTextCues[this._player.activeTextCues.length - 1].startTime) {\n+      this._player.activeTextCues = [];\n+      this._player.onCueChange({\n+        payload: {\n+          cues: []\n+        }\n+      });\n+    } else {\n+      let _activeCuesChanged = false;\n+      for (let _activeTextCuesIndex = 0; _activeTextCuesIndex < this._player.activeTextCues.length; _activeTextCuesIndex++) {\n+        let _cue = this._player.activeTextCues[_activeTextCuesIndex];\n+        if (this._player.currentTime < _cue.startTime || _cue.endTime < this._player.currentTime) {\n+          this._player.activeTextCues.splice(_activeTextCuesIndex, 1);\n+          _activeCuesChanged = true;\n+        }\n+      }\n+      while (this._player.currentTime > track.cues[this._externalCueIndex].startTime) {\n+        this._player.activeTextCues.push(track.cues[this._externalCueIndex]);\n+        this._externalCueIndex++;\n+        _activeCuesChanged = true;\n+      }\n+      if (_activeCuesChanged) {\n+        this._player.onCueChange({\n+          payload: {\n+            cues: this._player.activeTextCues\n+          }\n+        });\n+      }\n+    }\n+  }\n+\n+  /**\n+   * updating the index of the text cues to the right location after a user seeked.\n+   * @returns {void}\n+   * @private\n+   */\n+  _maybeSetExternalCueIndex(): void {\n+    const textTrack = this._player.getTracks(TrackType.TEXT).filter(track => track.active && track.external)[0];\n+    if (textTrack && textTrack.external) {\n+      let cues = textTrack.cues;\n+      let i = 0;\n+      while (this._player.currentTime > cues[i].startTime && i < cues.length) {\n+        i++;\n+      }\n+      this._externalCueIndex = i;\n+    }\n+  }\n+\n+  /**\n+   * adding external tracks (native or moduled tracks)\n+   * @returns {Promise<any>} returns a promise when all the tracks were parsed and added.\n+   * @public\n+   */\n+  addTracks(): void {\n+    const captions = this._player.config.sources.captions;\n+    if (!captions) {\n+      return;\n+    }\n+    let textTracks = this._player.getTracks(TrackType.TEXT);\n+    let textTracksLength = textTracks.length || 0;\n+    captions.forEach(caption => {\n+      let track = new TextTrack({\n+        active: false,\n+        index: textTracksLength++,\n+        kind: \"subtitles\",\n+        label: caption.label,\n+        language: caption.language,\n+        external: true,\n+        url: caption.url,\n+        type: caption.type,\n+        cues: []\n+      });\n+      let sameLangTrack = textTracks.find(textTrack => caption.language === textTrack.language);\n+      // replace the track with a new one, update only the cues to []\n+      if (sameLangTrack) {\n+        this._player.setTextTrackCues(track);\n+      } else {\n+        this._player.addTrack(track);\n+      }\n+      if (this._player.config.playback.useNativeTextTrack)\n+        this._setNativeTextTrack(track);\n+    });\n+  }\n+\n+  /**\n+   * selects external track start listenning to cues\n+   * @param {TextTrack} textTrack - selected text track\n+   * @returns {void}\n+   * @public\n+   */\n+  selectTextTrack(textTrack: TextTrack): Promise<*> {\n+    return new Promise((resolve) => {\n+      if (textTrack.cues.length > 0 && !this._player.config.playback.useNativeTextTrack) {","path":"src/track/external-captions-handler.js","position":280,"original_position":280,"commit_id":"4018a086f62b180ad6a86642e4e419635abd55b6","original_commit_id":"4018a086f62b180ad6a86642e4e419635abd55b6","user":{"login":"OrenMe","id":5461862,"node_id":"MDQ6VXNlcjU0NjE4NjI=","avatar_url":"https://avatars1.githubusercontent.com/u/5461862?v=4","gravatar_id":"","url":"https://api.github.com/users/OrenMe","html_url":"https://github.com/OrenMe","followers_url":"https://api.github.com/users/OrenMe/followers","following_url":"https://api.github.com/users/OrenMe/following{/other_user}","gists_url":"https://api.github.com/users/OrenMe/gists{/gist_id}","starred_url":"https://api.github.com/users/OrenMe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OrenMe/subscriptions","organizations_url":"https://api.github.com/users/OrenMe/orgs","repos_url":"https://api.github.com/users/OrenMe/repos","events_url":"https://api.github.com/users/OrenMe/events{/privacy}","received_events_url":"https://api.github.com/users/OrenMe/received_events","type":"User","site_admin":false},"body":"if you follow the comment about managing `_cuesInProcessMap` (which should be `_textTrackStatus`) then you can just check for the status if it's `READY` and set it instead of checking its cues","created_at":"2018-06-19T06:36:30Z","updated_at":"2018-06-19T06:39:05Z","html_url":"https://github.com/kaltura/playkit-js/pull/237#discussion_r196308168","pull_request_url":"https://api.github.com/repos/kaltura/playkit-js/pulls/237","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/comments/196308168"},"html":{"href":"https://github.com/kaltura/playkit-js/pull/237#discussion_r196308168"},"pull_request":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/237"}}},"pull_request":{"url":"https://api.github.com/repos/kaltura/playkit-js/pulls/237","id":194299585,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk0Mjk5NTg1","html_url":"https://github.com/kaltura/playkit-js/pull/237","diff_url":"https://github.com/kaltura/playkit-js/pull/237.diff","patch_url":"https://github.com/kaltura/playkit-js/pull/237.patch","issue_url":"https://api.github.com/repos/kaltura/playkit-js/issues/237","number":237,"state":"open","locked":false,"title":"feat(FEC-8232): support external captions","user":{"login":"odedhutzler","id":31587052,"node_id":"MDQ6VXNlcjMxNTg3MDUy","avatar_url":"https://avatars2.githubusercontent.com/u/31587052?v=4","gravatar_id":"","url":"https://api.github.com/users/odedhutzler","html_url":"https://github.com/odedhutzler","followers_url":"https://api.github.com/users/odedhutzler/followers","following_url":"https://api.github.com/users/odedhutzler/following{/other_user}","gists_url":"https://api.github.com/users/odedhutzler/gists{/gist_id}","starred_url":"https://api.github.com/users/odedhutzler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/odedhutzler/subscriptions","organizations_url":"https://api.github.com/users/odedhutzler/orgs","repos_url":"https://api.github.com/users/odedhutzler/repos","events_url":"https://api.github.com/users/odedhutzler/events{/privacy}","received_events_url":"https://api.github.com/users/odedhutzler/received_events","type":"User","site_admin":false},"body":"### Description of the Changes\r\n\r\nfirst commit for pre-initial-review\r\n\r\n### CheckLists\r\n\r\n- [ ] changes have been done against master branch, and PR does not conflict\r\n- [ ] new unit / functional tests have been added (whenever applicable)\r\n- [ ] test are passing in local environment \r\n- [ ] Travis tests are passing (or test results are not worse than on master branch :))\r\n- [ ] Docs have been updated\r\n","created_at":"2018-06-12T14:29:00Z","updated_at":"2018-06-19T06:39:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fbd5eabede79de22db908a86778c5fbeb5706dc7","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/kaltura/playkit-js/pulls/237/commits","review_comments_url":"https://api.github.com/repos/kaltura/playkit-js/pulls/237/comments","review_comment_url":"https://api.github.com/repos/kaltura/playkit-js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kaltura/playkit-js/issues/237/comments","statuses_url":"https://api.github.com/repos/kaltura/playkit-js/statuses/4018a086f62b180ad6a86642e4e419635abd55b6","head":{"label":"kaltura:FEC-8232","ref":"FEC-8232","sha":"4018a086f62b180ad6a86642e4e419635abd55b6","user":{"login":"kaltura","id":319096,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxOTA5Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/319096?v=4","gravatar_id":"","url":"https://api.github.com/users/kaltura","html_url":"https://github.com/kaltura","followers_url":"https://api.github.com/users/kaltura/followers","following_url":"https://api.github.com/users/kaltura/following{/other_user}","gists_url":"https://api.github.com/users/kaltura/gists{/gist_id}","starred_url":"https://api.github.com/users/kaltura/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaltura/subscriptions","organizations_url":"https://api.github.com/users/kaltura/orgs","repos_url":"https://api.github.com/users/kaltura/repos","events_url":"https://api.github.com/users/kaltura/events{/privacy}","received_events_url":"https://api.github.com/users/kaltura/received_events","type":"Organization","site_admin":false},"repo":{"id":80407629,"node_id":"MDEwOlJlcG9zaXRvcnk4MDQwNzYyOQ==","name":"playkit-js","full_name":"kaltura/playkit-js","owner":{"login":"kaltura","id":319096,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxOTA5Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/319096?v=4","gravatar_id":"","url":"https://api.github.com/users/kaltura","html_url":"https://github.com/kaltura","followers_url":"https://api.github.com/users/kaltura/followers","following_url":"https://api.github.com/users/kaltura/following{/other_user}","gists_url":"https://api.github.com/users/kaltura/gists{/gist_id}","starred_url":"https://api.github.com/users/kaltura/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaltura/subscriptions","organizations_url":"https://api.github.com/users/kaltura/orgs","repos_url":"https://api.github.com/users/kaltura/repos","events_url":"https://api.github.com/users/kaltura/events{/privacy}","received_events_url":"https://api.github.com/users/kaltura/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kaltura/playkit-js","description":"State of the Art HTML5 Player","fork":false,"url":"https://api.github.com/repos/kaltura/playkit-js","forks_url":"https://api.github.com/repos/kaltura/playkit-js/forks","keys_url":"https://api.github.com/repos/kaltura/playkit-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kaltura/playkit-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kaltura/playkit-js/teams","hooks_url":"https://api.github.com/repos/kaltura/playkit-js/hooks","issue_events_url":"https://api.github.com/repos/kaltura/playkit-js/issues/events{/number}","events_url":"https://api.github.com/repos/kaltura/playkit-js/events","assignees_url":"https://api.github.com/repos/kaltura/playkit-js/assignees{/user}","branches_url":"https://api.github.com/repos/kaltura/playkit-js/branches{/branch}","tags_url":"https://api.github.com/repos/kaltura/playkit-js/tags","blobs_url":"https://api.github.com/repos/kaltura/playkit-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kaltura/playkit-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kaltura/playkit-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/kaltura/playkit-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kaltura/playkit-js/statuses/{sha}","languages_url":"https://api.github.com/repos/kaltura/playkit-js/languages","stargazers_url":"https://api.github.com/repos/kaltura/playkit-js/stargazers","contributors_url":"https://api.github.com/repos/kaltura/playkit-js/contributors","subscribers_url":"https://api.github.com/repos/kaltura/playkit-js/subscribers","subscription_url":"https://api.github.com/repos/kaltura/playkit-js/subscription","commits_url":"https://api.github.com/repos/kaltura/playkit-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/kaltura/playkit-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/kaltura/playkit-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/kaltura/playkit-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/kaltura/playkit-js/contents/{+path}","compare_url":"https://api.github.com/repos/kaltura/playkit-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kaltura/playkit-js/merges","archive_url":"https://api.github.com/repos/kaltura/playkit-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kaltura/playkit-js/downloads","issues_url":"https://api.github.com/repos/kaltura/playkit-js/issues{/number}","pulls_url":"https://api.github.com/repos/kaltura/playkit-js/pulls{/number}","milestones_url":"https://api.github.com/repos/kaltura/playkit-js/milestones{/number}","notifications_url":"https://api.github.com/repos/kaltura/playkit-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kaltura/playkit-js/labels{/name}","releases_url":"https://api.github.com/repos/kaltura/playkit-js/releases{/id}","deployments_url":"https://api.github.com/repos/kaltura/playkit-js/deployments","created_at":"2017-01-30T09:22:52Z","updated_at":"2018-06-17T11:43:05Z","pushed_at":"2018-06-18T16:05:36Z","git_url":"git://github.com/kaltura/playkit-js.git","ssh_url":"git@github.com:kaltura/playkit-js.git","clone_url":"https://github.com/kaltura/playkit-js.git","svn_url":"https://github.com/kaltura/playkit-js","homepage":"","size":47882,"stargazers_count":19,"watchers_count":19,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":6,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":5,"open_issues":6,"watchers":19,"default_branch":"master"}},"base":{"label":"kaltura:master","ref":"master","sha":"2393dd691bf14390aeb8604278e5cc52e24e758b","user":{"login":"kaltura","id":319096,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxOTA5Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/319096?v=4","gravatar_id":"","url":"https://api.github.com/users/kaltura","html_url":"https://github.com/kaltura","followers_url":"https://api.github.com/users/kaltura/followers","following_url":"https://api.github.com/users/kaltura/following{/other_user}","gists_url":"https://api.github.com/users/kaltura/gists{/gist_id}","starred_url":"https://api.github.com/users/kaltura/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaltura/subscriptions","organizations_url":"https://api.github.com/users/kaltura/orgs","repos_url":"https://api.github.com/users/kaltura/repos","events_url":"https://api.github.com/users/kaltura/events{/privacy}","received_events_url":"https://api.github.com/users/kaltura/received_events","type":"Organization","site_admin":false},"repo":{"id":80407629,"node_id":"MDEwOlJlcG9zaXRvcnk4MDQwNzYyOQ==","name":"playkit-js","full_name":"kaltura/playkit-js","owner":{"login":"kaltura","id":319096,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxOTA5Ng==","avatar_url":"https://avatars0.githubusercontent.com/u/319096?v=4","gravatar_id":"","url":"https://api.github.com/users/kaltura","html_url":"https://github.com/kaltura","followers_url":"https://api.github.com/users/kaltura/followers","following_url":"https://api.github.com/users/kaltura/following{/other_user}","gists_url":"https://api.github.com/users/kaltura/gists{/gist_id}","starred_url":"https://api.github.com/users/kaltura/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaltura/subscriptions","organizations_url":"https://api.github.com/users/kaltura/orgs","repos_url":"https://api.github.com/users/kaltura/repos","events_url":"https://api.github.com/users/kaltura/events{/privacy}","received_events_url":"https://api.github.com/users/kaltura/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/kaltura/playkit-js","description":"State of the Art HTML5 Player","fork":false,"url":"https://api.github.com/repos/kaltura/playkit-js","forks_url":"https://api.github.com/repos/kaltura/playkit-js/forks","keys_url":"https://api.github.com/repos/kaltura/playkit-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kaltura/playkit-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kaltura/playkit-js/teams","hooks_url":"https://api.github.com/repos/kaltura/playkit-js/hooks","issue_events_url":"https://api.github.com/repos/kaltura/playkit-js/issues/events{/number}","events_url":"https://api.github.com/repos/kaltura/playkit-js/events","assignees_url":"https://api.github.com/repos/kaltura/playkit-js/assignees{/user}","branches_url":"https://api.github.com/repos/kaltura/playkit-js/branches{/branch}","tags_url":"https://api.github.com/repos/kaltura/playkit-js/tags","blobs_url":"https://api.github.com/repos/kaltura/playkit-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kaltura/playkit-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kaltura/playkit-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/kaltura/playkit-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kaltura/playkit-js/statuses/{sha}","languages_url":"https://api.github.com/repos/kaltura/playkit-js/languages","stargazers_url":"https://api.github.com/repos/kaltura/playkit-js/stargazers","contributors_url":"https://api.github.com/repos/kaltura/playkit-js/contributors","subscribers_url":"https://api.github.com/repos/kaltura/playkit-js/subscribers","subscription_url":"https://api.github.com/repos/kaltura/playkit-js/subscription","commits_url":"https://api.github.com/repos/kaltura/playkit-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/kaltura/playkit-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/kaltura/playkit-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/kaltura/playkit-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/kaltura/playkit-js/contents/{+path}","compare_url":"https://api.github.com/repos/kaltura/playkit-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kaltura/playkit-js/merges","archive_url":"https://api.github.com/repos/kaltura/playkit-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kaltura/playkit-js/downloads","issues_url":"https://api.github.com/repos/kaltura/playkit-js/issues{/number}","pulls_url":"https://api.github.com/repos/kaltura/playkit-js/pulls{/number}","milestones_url":"https://api.github.com/repos/kaltura/playkit-js/milestones{/number}","notifications_url":"https://api.github.com/repos/kaltura/playkit-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kaltura/playkit-js/labels{/name}","releases_url":"https://api.github.com/repos/kaltura/playkit-js/releases{/id}","deployments_url":"https://api.github.com/repos/kaltura/playkit-js/deployments","created_at":"2017-01-30T09:22:52Z","updated_at":"2018-06-17T11:43:05Z","pushed_at":"2018-06-18T16:05:36Z","git_url":"git://github.com/kaltura/playkit-js.git","ssh_url":"git@github.com:kaltura/playkit-js.git","clone_url":"https://github.com/kaltura/playkit-js.git","svn_url":"https://github.com/kaltura/playkit-js","homepage":"","size":47882,"stargazers_count":19,"watchers_count":19,"language":"JavaScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":6,"license":{"key":"agpl-3.0","name":"GNU Affero General Public License v3.0","spdx_id":"AGPL-3.0","url":"https://api.github.com/licenses/agpl-3.0","node_id":"MDc6TGljZW5zZTE="},"forks":5,"open_issues":6,"watchers":19,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/237"},"html":{"href":"https://github.com/kaltura/playkit-js/pull/237"},"issue":{"href":"https://api.github.com/repos/kaltura/playkit-js/issues/237"},"comments":{"href":"https://api.github.com/repos/kaltura/playkit-js/issues/237/comments"},"review_comments":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/237/comments"},"review_comment":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kaltura/playkit-js/pulls/237/commits"},"statuses":{"href":"https://api.github.com/repos/kaltura/playkit-js/statuses/4018a086f62b180ad6a86642e4e419635abd55b6"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"OrenMe"}}