소스 검색

use largest resolution mp4 video available

girst 4 년 전
부모
커밋
e2b8e17f85
4개의 변경된 파일29개의 추가작업 그리고 5개의 파일을 삭제
  1. 7 2
      src/parser.nim
  2. 15 0
      src/parserutils.nim
  3. 1 0
      src/types.nim
  4. 6 3
      src/views/tweet.nim

+ 7 - 2
src/parser.nim

@@ -87,10 +87,15 @@ proc parseVideo(js: JsonNode): Video =
     result.description = description.getStr
 
   for v in js{"video_info", "variants"}:
+    let
+      contentType = parseEnum[VideoType](v{"content_type"}.getStr("summary"))
+      url = v{"url"}.getStr
+      resolution = getMp4Resolution(url)  # only available if contentType == mp4
     result.variants.add VideoVariant(
-      contentType: parseEnum[VideoType](v{"content_type"}.getStr("summary")),
+      contentType: contentType,
       bitrate: v{"bitrate"}.getInt,
-      url: v{"url"}.getStr
+      url: url,
+      resolution: resolution
     )
 
 proc parsePromoVideo(js: JsonNode): Video =

+ 15 - 0
src/parserutils.nim

@@ -137,6 +137,21 @@ proc getSource*(js: JsonNode): string =
   let src = js{"source"}.getStr
   result = src.substr(src.find('>') + 1, src.rfind('<') - 1)
 
+proc getMp4Resolution*(url: string): int =
+  # parses the height out of a URL like this one:
+  # https://video.twimg.com/ext_tw_video/<tweet-id>/pu/vid/720x1280/<random>.mp4
+  const vidSep = "/vid/"
+  let
+    vidIdx = url.find(vidSep) + vidSep.len
+    resIdx = url.find('x', vidIdx) + 1
+    res = url[resIdx ..< url.find("/", resIdx)]
+
+  try:
+    return parseInt(res)
+  except ValueError:
+    # cannot determine resolution (e.g. m3u8/non-mp4 video)
+    return 0
+
 proc extractSlice(js: JsonNode): Slice[int] =
   result = js["indices"][0].getInt ..< js["indices"][1].getInt
 

+ 1 - 0
src/types.nim

@@ -75,6 +75,7 @@ type
     contentType*: VideoType
     url*: string
     bitrate*: int
+    resolution*: int
 
   Video* = object
     durationMs*: int

+ 6 - 3
src/views/tweet.nim

@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: AGPL-3.0-only
-import strutils, sequtils, strformat, options
+import strutils, sequtils, strformat, options, algorithm
 import karax/[karaxdsl, vdom, vstyles]
 from jester import Request
 
@@ -105,8 +105,11 @@ proc renderVideo*(video: Video; prefs: Prefs; path: string): VNode =
           img(src=thumb)
           renderVideoDisabled(video, path)
         else:
-          let vid = video.variants.filterIt(it.contentType == playbackType)
-          let source = if prefs.proxyVideos: getVidUrl(vid[0].url) else: vid[0].url
+          let
+            vars = video.variants.filterIt(it.contentType == playbackType)
+            vidUrl = vars.sortedByIt(it.resolution)[^1].url
+            source = if prefs.proxyVideos: getVidUrl(vidUrl)
+                     else: vidUrl
           case playbackType
           of mp4:
             if prefs.muteVideos: