feat: Add support for Twitter/X URL with Safari compatibility
This commit is contained in:
@@ -56,12 +56,18 @@ export function prepareDownloadFlags(
|
||||
// Get format sort option if user specified it
|
||||
const formatSortValue = userFormatSort || userFormatSort2;
|
||||
|
||||
// Check if this is a Twitter/X URL - always use mp4 for Safari compatibility
|
||||
const isTwitterUrl =
|
||||
videoUrl.includes("x.com") || videoUrl.includes("twitter.com");
|
||||
|
||||
// Determine merge output format: use user's choice or default to mp4
|
||||
// However, if user is sorting by resolution (likely demanding 4K/VP9), default to MKV
|
||||
// However, if user is sorting by resolution (likely demanding 4K/VP9), default to WebM
|
||||
// because VP9/AV1 in MP4 (mp4v2) is often problematic for Safari/QuickTime.
|
||||
// Exception: Twitter/X always uses mp4 for Safari compatibility
|
||||
let defaultMergeFormat = "mp4";
|
||||
if (formatSortValue && formatSortValue.includes("res")) {
|
||||
if (!isTwitterUrl && formatSortValue && formatSortValue.includes("res")) {
|
||||
// Use WebM for high-res (likely VP9/AV1) as it's supported by Safari 14+ and Chrome
|
||||
// But skip this for Twitter/X to ensure Safari compatibility
|
||||
defaultMergeFormat = "webm";
|
||||
}
|
||||
const mergeOutputFormat = userMergeOutputFormat || defaultMergeFormat;
|
||||
@@ -84,6 +90,18 @@ export function prepareDownloadFlags(
|
||||
logger.info("Using user-specified format sort:", formatSortValue);
|
||||
}
|
||||
|
||||
// Add Twitter/X specific flags - always use MP4 with H.264 for Safari compatibility
|
||||
if (isTwitterUrl) {
|
||||
// Force MP4 format with H.264 codec for Safari compatibility
|
||||
// Twitter/X videos should use MP4 container regardless of resolution
|
||||
if (!config.f && !config.format) {
|
||||
flags.format =
|
||||
"bestvideo[ext=mp4][vcodec^=avc1]+bestaudio[ext=m4a]/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best";
|
||||
}
|
||||
// Ensure merge output format is mp4 (already handled above, but log it)
|
||||
logger.info("Twitter/X URL detected - using MP4 format for Safari compatibility");
|
||||
}
|
||||
|
||||
// Add YouTube specific flags if it's a YouTube URL
|
||||
// Always apply preferred formats for YouTube to ensure codec compatibility (H.264/AAC for Safari)
|
||||
if (videoUrl.includes("youtube.com") || videoUrl.includes("youtu.be")) {
|
||||
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
import * as storageService from "../../storageService";
|
||||
import { Video } from "../../storageService";
|
||||
import { BaseDownloader } from "../BaseDownloader";
|
||||
import { getProviderScript } from "./ytdlpHelpers";
|
||||
import { prepareDownloadFlags } from "./ytdlpConfig";
|
||||
import { getProviderScript } from "./ytdlpHelpers";
|
||||
import { extractVideoMetadata } from "./ytdlpMetadata";
|
||||
import { processSubtitles } from "./ytdlpSubtitle";
|
||||
|
||||
@@ -112,7 +112,7 @@ export async function downloadVideo(
|
||||
videoDescription = metadata.videoDescription;
|
||||
thumbnailUrl = metadata.thumbnailUrl;
|
||||
source = metadata.source;
|
||||
|
||||
|
||||
// Extract channel URL from info if available
|
||||
channelUrl = info.channel_url || info.uploader_url || null;
|
||||
|
||||
@@ -283,17 +283,14 @@ export async function downloadVideo(
|
||||
title: videoTitle || "Video",
|
||||
author: videoAuthor || "Unknown",
|
||||
description: videoDescription,
|
||||
date:
|
||||
videoDate || new Date().toISOString().slice(0, 10).replace(/-/g, ""),
|
||||
date: videoDate || new Date().toISOString().slice(0, 10).replace(/-/g, ""),
|
||||
source: source, // Use extracted source
|
||||
sourceUrl: videoUrl,
|
||||
videoFilename: finalVideoFilename,
|
||||
thumbnailFilename: thumbnailSaved ? finalThumbnailFilename : undefined,
|
||||
thumbnailUrl: thumbnailUrl || undefined,
|
||||
videoPath: `/videos/${finalVideoFilename}`,
|
||||
thumbnailPath: thumbnailSaved
|
||||
? `/images/${finalThumbnailFilename}`
|
||||
: null,
|
||||
thumbnailPath: thumbnailSaved ? `/images/${finalThumbnailFilename}` : null,
|
||||
subtitles: subtitles.length > 0 ? subtitles : undefined,
|
||||
duration: undefined, // Will be populated below
|
||||
channelUrl: channelUrl || undefined,
|
||||
@@ -369,4 +366,3 @@ export async function downloadVideo(
|
||||
|
||||
return videoData;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user