From 8556a5fe2c950569bcfe096c6d942197251fe462 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 17 Dec 2023 23:05:43 +0600 Subject: [PATCH 1/2] twitter: fix videos only within affected time range --- src/modules/processing/matchActionDecider.js | 9 ++++++++- src/modules/processing/services/twitter.js | 21 +++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js index 4efd0f12..face4433 100644 --- a/src/modules/processing/matchActionDecider.js +++ b/src/modules/processing/matchActionDecider.js @@ -40,7 +40,6 @@ export default function(r, host, audioFormat, isAudioOnly, lang, isAudioMuted, d case "bilibili": params = { type: "render" }; break; - case "twitter": case "youtube": params = { type: r.type }; break; @@ -55,6 +54,14 @@ export default function(r, host, audioFormat, isAudioOnly, lang, isAudioMuted, d responseType = 1; } break; + + case "twitter": + if (r.type === "remux") { + params = { type: r.type }; + } else { + responseType = 1; + } + break; case "vk": case "douyin": diff --git a/src/modules/processing/services/twitter.js b/src/modules/processing/services/twitter.js index 110a43e1..2c36419f 100644 --- a/src/modules/processing/services/twitter.js +++ b/src/modules/processing/services/twitter.js @@ -5,6 +5,10 @@ function bestQuality(arr) { return arr.filter(v => v["content_type"] === "video/mp4").sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"] } +// fix all videos affected by the container bug in twitter muxer (took them over two weeks to fix it????) +const badContainerStart = new Date(1701446400000); +const badContainerEnd = new Date(1702605600000); + export default async function(obj) { let _headers = { "user-agent": genericUserAgent, @@ -60,17 +64,24 @@ export default async function(obj) { let single, multiple = [], media = baseMedia["media"]; media = media.filter((i) => { if (i["type"] === "video" || i["type"] === "animated_gif") return true }); + let tweetDate = new Date(baseTweet.created_at), + needsFixing = tweetDate > badContainerStart && tweetDate < badContainerEnd; + if (media.length > 1) { for (let i in media) { - multiple.push({ - type: "video", - thumb: media[i]["media_url_https"], - url: createStream({ + let downloadUrl = bestQuality(media[i]["video_info"]["variants"]); + if (needsFixing) { + downloadUrl = createStream({ service: "twitter", type: "remux", u: bestQuality(media[i]["video_info"]["variants"]), filename: `twitter_${obj.id}_${Number(i) + 1}.mp4` }) + } + multiple.push({ + type: "video", + thumb: media[i]["media_url_https"], + url: downloadUrl }) } } else if (media.length === 1) { @@ -81,7 +92,7 @@ export default async function(obj) { if (single) { return { - type: "remux", + type: needsFixing? "remux" : "normal", urls: single, filename: `twitter_${obj.id}.mp4`, audioFilename: `twitter_${obj.id}_audio` From 4834f2155430b0aaa49c667310c39384c08ffea8 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 17 Dec 2023 23:45:15 +0600 Subject: [PATCH 2/2] twitter: use original media timestamp for fix check --- src/modules/processing/services/twitter.js | 30 ++++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/modules/processing/services/twitter.js b/src/modules/processing/services/twitter.js index 2c36419f..b59e0d99 100644 --- a/src/modules/processing/services/twitter.js +++ b/src/modules/processing/services/twitter.js @@ -1,13 +1,22 @@ import { genericUserAgent } from "../../config.js"; import { createStream } from "../../stream/manage.js"; -function bestQuality(arr) { - return arr.filter(v => v["content_type"] === "video/mp4").sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"] -} - // fix all videos affected by the container bug in twitter muxer (took them over two weeks to fix it????) const badContainerStart = new Date(1701446400000); const badContainerEnd = new Date(1702605600000); +const TWITTER_EPOCH = 1288834974657n; + +function needsFixing(media) { + const representativeId = media.source_status_id_str ?? media.id_str; + const mediaTimestamp = new Date( + Number((BigInt(representativeId) >> 22n) + TWITTER_EPOCH) + ) + return mediaTimestamp > badContainerStart && mediaTimestamp < badContainerEnd; +} + +function bestQuality(arr) { + return arr.filter(v => v["content_type"] === "video/mp4").sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"] +} export default async function(obj) { let _headers = { @@ -64,13 +73,14 @@ export default async function(obj) { let single, multiple = [], media = baseMedia["media"]; media = media.filter((i) => { if (i["type"] === "video" || i["type"] === "animated_gif") return true }); - let tweetDate = new Date(baseTweet.created_at), - needsFixing = tweetDate > badContainerStart && tweetDate < badContainerEnd; + if (media.length === 0) { + return { error: 'ErrorNoVideosInTweet' } + } if (media.length > 1) { for (let i in media) { let downloadUrl = bestQuality(media[i]["video_info"]["variants"]); - if (needsFixing) { + if (needsFixing(media[i])) { downloadUrl = createStream({ service: "twitter", type: "remux", @@ -84,15 +94,13 @@ export default async function(obj) { url: downloadUrl }) } - } else if (media.length === 1) { - single = bestQuality(media[0]["video_info"]["variants"]) } else { - return { error: 'ErrorNoVideosInTweet' } + single = bestQuality(media[0]["video_info"]["variants"]) } if (single) { return { - type: needsFixing? "remux" : "normal", + type: needsFixing(media[0]) ? "remux" : "normal", urls: single, filename: `twitter_${obj.id}.mp4`, audioFilename: `twitter_${obj.id}_audio`