mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
fix(extension): import the best-quality Twitter video variant (#1351)
This commit is contained in:
parent
7e7e820489
commit
785c96e682
2 changed files with 111 additions and 4 deletions
|
|
@ -56,13 +56,45 @@ interface MediaEntity {
|
|||
}
|
||||
}
|
||||
video_info?: {
|
||||
variants?: Array<{
|
||||
url: string
|
||||
}>
|
||||
variants?: VideoVariant[]
|
||||
duration_millis?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface VideoVariant {
|
||||
url: string
|
||||
bitrate?: number
|
||||
content_type?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Twitter returns several video variants for a single video: an HLS `.m3u8`
|
||||
* playlist (no bitrate) plus multiple `video/mp4` renditions at different
|
||||
* bitrates, in no guaranteed order. Taking `variants[0]` therefore often stored
|
||||
* the HLS playlist URL (not a directly usable file) or the lowest-quality clip.
|
||||
* Pick the highest-bitrate MP4 instead, falling back to the first variant when
|
||||
* no MP4 rendition is present.
|
||||
*/
|
||||
export function pickBestVideoVariantUrl(
|
||||
variants: VideoVariant[] | undefined,
|
||||
): string {
|
||||
if (!variants || variants.length === 0) return ""
|
||||
|
||||
const mp4s = variants.filter(
|
||||
(v) => v.content_type === "video/mp4" || /\.mp4(?:\?|$)/i.test(v.url),
|
||||
)
|
||||
const pool = mp4s.length > 0 ? mp4s : variants
|
||||
|
||||
let best = pool[0]
|
||||
for (const variant of pool) {
|
||||
if ((variant.bitrate ?? 0) > (best?.bitrate ?? 0)) {
|
||||
best = variant
|
||||
}
|
||||
}
|
||||
|
||||
return best?.url || ""
|
||||
}
|
||||
|
||||
export interface Tweet {
|
||||
__typename?: string
|
||||
lang?: string
|
||||
|
|
@ -257,7 +289,7 @@ export function transformTweetData(
|
|||
const videos = media
|
||||
.filter((m) => m.type === "video")
|
||||
.map((m) => ({
|
||||
url: m.video_info?.variants?.[0]?.url || "",
|
||||
url: pickBestVideoVariantUrl(m.video_info?.variants),
|
||||
thumbnail_url: m.media_url_https,
|
||||
duration: m.video_info?.duration_millis || 0,
|
||||
}))
|
||||
|
|
|
|||
75
apps/browser-extension/utils/twitter-video-variant.test.ts
Normal file
75
apps/browser-extension/utils/twitter-video-variant.test.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import { describe, expect, it } from "bun:test"
|
||||
import { pickBestVideoVariantUrl } from "./twitter-utils"
|
||||
|
||||
describe("pickBestVideoVariantUrl", () => {
|
||||
it("returns an empty string when there are no variants", () => {
|
||||
expect(pickBestVideoVariantUrl(undefined)).toBe("")
|
||||
expect(pickBestVideoVariantUrl([])).toBe("")
|
||||
})
|
||||
|
||||
it("picks the highest-bitrate mp4, not the first variant", () => {
|
||||
const variants = [
|
||||
{
|
||||
url: "https://video.twimg.com/playlist.m3u8",
|
||||
content_type: "application/x-mpegURL",
|
||||
},
|
||||
{
|
||||
url: "https://video.twimg.com/low.mp4",
|
||||
content_type: "video/mp4",
|
||||
bitrate: 256000,
|
||||
},
|
||||
{
|
||||
url: "https://video.twimg.com/high.mp4",
|
||||
content_type: "video/mp4",
|
||||
bitrate: 2176000,
|
||||
},
|
||||
{
|
||||
url: "https://video.twimg.com/mid.mp4",
|
||||
content_type: "video/mp4",
|
||||
bitrate: 832000,
|
||||
},
|
||||
]
|
||||
expect(pickBestVideoVariantUrl(variants)).toBe(
|
||||
"https://video.twimg.com/high.mp4",
|
||||
)
|
||||
})
|
||||
|
||||
it("does not return the HLS playlist when mp4 renditions exist", () => {
|
||||
const variants = [
|
||||
{
|
||||
url: "https://video.twimg.com/playlist.m3u8",
|
||||
content_type: "application/x-mpegURL",
|
||||
},
|
||||
{
|
||||
url: "https://video.twimg.com/only.mp4",
|
||||
content_type: "video/mp4",
|
||||
bitrate: 632000,
|
||||
},
|
||||
]
|
||||
expect(pickBestVideoVariantUrl(variants)).toBe(
|
||||
"https://video.twimg.com/only.mp4",
|
||||
)
|
||||
})
|
||||
|
||||
it("falls back to the first variant when no mp4 is present", () => {
|
||||
const variants = [
|
||||
{
|
||||
url: "https://video.twimg.com/playlist.m3u8",
|
||||
content_type: "application/x-mpegURL",
|
||||
},
|
||||
]
|
||||
expect(pickBestVideoVariantUrl(variants)).toBe(
|
||||
"https://video.twimg.com/playlist.m3u8",
|
||||
)
|
||||
})
|
||||
|
||||
it("detects mp4 by extension when content_type is absent", () => {
|
||||
const variants = [
|
||||
{ url: "https://video.twimg.com/240/vid.mp4?tag=12" },
|
||||
{ url: "https://video.twimg.com/720/vid.mp4?tag=12", bitrate: 2176000 },
|
||||
]
|
||||
expect(pickBestVideoVariantUrl(variants)).toBe(
|
||||
"https://video.twimg.com/720/vid.mp4?tag=12",
|
||||
)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Reference in a new issue