Greasy Fork is available in English.

embyLaunchPotplayer

try to take over the world!

От 20.12.2020. Виж последната версия.

  1. // ==UserScript==
  2. // @name embyLaunchPotplayer
  3. // @name:en embyLaunchPotplayer
  4. // @name:zh embyLaunchPotplayer
  5. // @name:zh-CN embyLaunchPotplayer
  6. // @namespace http://tampermonkey.net/
  7. // @version 0.8
  8. // @description try to take over the world!
  9. // @description:zh-cn emby调用外部播放器
  10. // @author @bpking
  11. // @include *emby*
  12. // @include *:8*
  13. // ==/UserScript==
  14. const domain = window.location.href;
  15. const api_key = "?api_key=1b52b02396894aa5a162233f0ef61681";
  16. const reg = /\/[a-z]{2,}\/\S*?id=/;
  17. const regResult = domain.match(reg)[0];
  18.  
  19. var timer = setInterval(function() {
  20. var potplayer = document.querySelectorAll("div[is='emby-scroller']:not(.hide) .potplayer")[0];
  21. if(!potplayer){
  22. var mainDetailButtons = document.querySelectorAll("div[is='emby-scroller']:not(.hide) .mainDetailButtons")[0];
  23. if(mainDetailButtons){
  24. var html = mainDetailButtons.innerHTML;
  25. mainDetailButtons.innerHTML = html
  26. +'<button id="potPlayer" type="button" class="detailButton emby-button potplayer" title="Potplayer"> <div class="detailButton-content"> <i class="md-icon detailButton-icon"></i> <div class="detailButton-text">PotPlayer</div> </div> </button>'
  27. +'<button id="playNext" type="button" class="detailButton emby-button playNext" title="稍后播放"> <div class="detailButton-content"> <i class="md-icon detailButton-icon"></i> <div class="detailButton-text">稍后播放</div> </div> </button>'
  28. +'<button id="iina" type="button" class="detailButton emby-button iina" title="IINA"> <div class="detailButton-content"> <i class="md-icon detailButton-icon"></i> <div class="detailButton-text">IINA</div> </div> </button>';
  29.  
  30. document.querySelector("div[is='emby-scroller']:not(.hide) #potPlayer").onclick = potPlayer;
  31. document.querySelector("div[is='emby-scroller']:not(.hide) #playNext").onclick = playNext;
  32. document.querySelector('#iina').onclick = iina;
  33. }
  34. }
  35. }, 1000)
  36.  
  37. function getItemInfo(){
  38. let domain = window.location.href;
  39. const itemInfoUrl = domain.replace(regResult, "/emby/Items/").split('&')[0] + "/PlaybackInfo" + api_key;
  40. console.log("itemInfo:" + itemInfoUrl);
  41. return new Promise((resolve, reject) => {
  42. fetch(itemInfoUrl).then(resp =>
  43. resp.json().then(data => resolve(data)).catch(e => {alert("网络错误,检查api_key是否设置正确 "+e.message)})
  44. )
  45. })
  46. }
  47.  
  48. function getSeek(){
  49. const resumeButton = document.querySelector("div[is='emby-scroller']:not(.hide) div.resumeButtonText");
  50. let seek = '';
  51. if (resumeButton) {
  52. if (resumeButton.innerText.includes('恢复播放于')) {
  53. seek = resumeButton.innerText.replace('恢复播放于', '');
  54. }
  55. }
  56. return seek;
  57. }
  58.  
  59. function getSubUrl(itemInfo, MediaSourceIndex){
  60. var selectSubtitles = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectSubtitles");
  61. let subTitleUrl = '';
  62. if (selectSubtitles) {
  63. if (selectSubtitles.value > 0) {
  64. console.log(selectSubtitles.value);
  65. if (itemInfo.MediaSources[MediaSourceIndex].MediaStreams[selectSubtitles.value].IsExternal) {
  66. let domain = window.location.href;
  67. const subtitleCodec = itemInfo.MediaSources[MediaSourceIndex].MediaStreams[selectSubtitles.value].Codec;
  68. subTitleUrl = domain.replace(regResult, "/emby/videos/").split('&')[0]
  69. + "/" + itemInfo.MediaSources[MediaSourceIndex].Id + "/Subtitles/" + selectSubtitles.value + "/"
  70. + MediaSourceIndex + "/Stream." + subtitleCodec + api_key;
  71. console.log(subTitleUrl);
  72. }
  73. }
  74. }
  75. return subTitleUrl;
  76. }
  77.  
  78.  
  79. var getVideoUrl = async function () {
  80. var selectSource = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectSource");
  81. var selectAudio = document.querySelector("div[is='emby-scroller']:not(.hide) select.selectAudio");
  82.  
  83. const itemInfo = await getItemInfo();
  84. let MediaSourceIndex = 0;
  85. for(let i = 0; i< itemInfo.MediaSources.length; i++){
  86. if(itemInfo.MediaSources[i].Id == selectSource.value){
  87. MediaSourceIndex = i;
  88. };
  89. }
  90. const container = itemInfo.MediaSources[MediaSourceIndex].Container;
  91. const MediaSourceId = selectSource.value;
  92. const PlaySessionId = itemInfo.PlaySessionId;
  93.  
  94. const subUrl = await getSubUrl(itemInfo, MediaSourceIndex);
  95.  
  96. let domain = window.location.href;
  97. const streamUrl = domain.replace(regResult, "/emby/videos/").split('&')[0]
  98. + "/stream." + container + api_key + "&Static=true" + "&MediaSourceId=" + MediaSourceId
  99. + "&PlaySessionId=" + PlaySessionId;
  100. return new Array(streamUrl, subUrl);
  101. }
  102.  
  103.  
  104. function potPlayer(){
  105. const seek = getSeek();
  106. getVideoUrl().then((videoUrl) => {
  107. console.log("videoUrl :"+videoUrl);
  108. const poturl = "potplayer://"+ encodeURI(videoUrl[0]) + " /sub=" + encodeURI(videoUrl[1])+" /current" + " /seek=" + seek;
  109. console.log("potUrl= " + poturl);
  110. window.open(poturl, "_blank");
  111. });
  112. }
  113.  
  114. //稍后播放,添加至potPlayer播放列表
  115. function playNext(){
  116. const seek = getSeek();
  117. getVideoUrl().then((videoUrl) => {
  118. console.log("videoUrl :"+videoUrl);
  119. const poturl = "potplayer://"+ encodeURI(videoUrl[0]) + " /sub=" + encodeURI(videoUrl[1])+" /current /add" + " /seek=" + seek;
  120. console.log("potUrl= " + poturl);
  121. window.open(poturl, "_blank");
  122. });
  123. }
  124.  
  125. function iina(){
  126. const seek = getSeek();
  127. getVideoUrl().then((videoUrl) => {
  128. console.log("videoUrl :"+videoUrl);
  129. var iinaurl = "iina://weblink?url=" +escape(videoUrl[0])+"&new_window=1";
  130. console.log("iinaUrl= " + iinaurl);
  131. window.open(iinaurl, "_blank");
  132. });
  133. }
  134.