[{"data":1,"prerenderedAt":1872},["ShallowReactive",2],{"docs-navigation":3,"\u002Fdocs\u002Fdeveloper\u002Farchitecture":298,"\u002Fdocs\u002Fdeveloper\u002Farchitecture-surround":1867},[4,165],{"title":5,"path":6,"stem":7,"children":8,"page":32},"Docs","\u002Fdocs","1.docs",[9,33,79,100,129,149],{"title":10,"path":11,"stem":12,"children":13,"icon":32},"Getting Started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[14,17,22,27],{"title":15,"path":11,"stem":12,"icon":16},"Introduction","i-lucide-house",{"title":18,"path":19,"stem":20,"icon":21},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","1.docs\u002F1.getting-started\u002F2.installation","i-lucide-download",{"title":23,"path":24,"stem":25,"icon":26},"Usage Guide","\u002Fdocs\u002Fgetting-started\u002Fusage","1.docs\u002F1.getting-started\u002F3.usage","i-lucide-sliders",{"title":28,"path":29,"stem":30,"icon":31},"Configuration Reference","\u002Fdocs\u002Fgetting-started\u002Fconfiguration","1.docs\u002F1.getting-started\u002F4.configuration","i-lucide-settings",false,{"title":34,"icon":35,"path":36,"stem":37,"children":38,"page":32},"Features","i-lucide-star","\u002Fdocs\u002Ffeatures","1.docs\u002F2.features",[39,44,49,54,59,64,69,74],{"title":40,"path":41,"stem":42,"icon":43},"Video Sniffing","\u002Fdocs\u002Ffeatures\u002Fvideo-sniffing","1.docs\u002F2.features\u002F1.video-sniffing","i-lucide-video",{"title":45,"path":46,"stem":47,"icon":48},"Audio Capture","\u002Fdocs\u002Ffeatures\u002Faudio-capture","1.docs\u002F2.features\u002F2.audio-capture","i-lucide-music",{"title":50,"path":51,"stem":52,"icon":53},"Image Download","\u002Fdocs\u002Ffeatures\u002Fimage-download","1.docs\u002F2.features\u002F3.image-download","i-lucide-image",{"title":55,"path":56,"stem":57,"icon":58},"Privacy & Security","\u002Fdocs\u002Ffeatures\u002Fprivacy-security","1.docs\u002F2.features\u002F4.privacy-security","i-lucide-shield-check",{"title":60,"path":61,"stem":62,"icon":63},"Format Conversion","\u002Fdocs\u002Ffeatures\u002Fformat-conversion","1.docs\u002F2.features\u002F5.format-conversion","i-lucide-arrow-left-right",{"title":65,"path":66,"stem":67,"icon":68},"Batch Download","\u002Fdocs\u002Ffeatures\u002Fbatch-download","1.docs\u002F2.features\u002F6.batch-download","i-lucide-layers",{"title":70,"path":71,"stem":72,"icon":73},"Keyboard Shortcuts","\u002Fdocs\u002Ffeatures\u002Fkeyboard-shortcuts","1.docs\u002F2.features\u002F7.keyboard-shortcuts","i-lucide-keyboard",{"title":75,"path":76,"stem":77,"icon":78},"Search & Filter","\u002Fdocs\u002Ffeatures\u002Fsearch-filter","1.docs\u002F2.features\u002F8.search-filter","i-lucide-search",{"title":80,"icon":81,"path":82,"stem":83,"children":84,"page":32},"Advanced","i-lucide-book-open","\u002Fdocs\u002Fadvanced","1.docs\u002F3.advanced",[85,90,95],{"title":86,"path":87,"stem":88,"icon":89},"Online Tools","\u002Fdocs\u002Fadvanced\u002Fonline-tools","1.docs\u002F3.advanced\u002F1.online-tools","i-lucide-globe",{"title":91,"path":92,"stem":93,"icon":94},"Browser Compatibility","\u002Fdocs\u002Fadvanced\u002Fbrowser-compatibility","1.docs\u002F3.advanced\u002F2.browser-compatibility","i-lucide-monitor-check",{"title":96,"path":97,"stem":98,"icon":99},"Download Engine Architecture","\u002Fdocs\u002Fadvanced\u002Fdownload-engine","1.docs\u002F3.advanced\u002F3.download-engine","i-lucide-cpu",{"title":101,"icon":102,"path":103,"stem":104,"children":105,"page":32},"Use Cases","i-lucide-lightbulb","\u002Fdocs\u002Fusecases","1.docs\u002F4.usecases",[106,111,115,120,125],{"title":107,"path":108,"stem":109,"icon":110},"Online Course Video Downloader for Offline Learning","\u002Fdocs\u002Fusecases\u002Fonline-courses","1.docs\u002F4.usecases\u002F1.online-courses","i-lucide-graduation-cap",{"title":112,"path":113,"stem":114,"icon":43},"Video Platform Stream Downloader for Public Media","\u002Fdocs\u002Fusecases\u002Fvideo-platforms","1.docs\u002F4.usecases\u002F2.video-platforms",{"title":116,"path":117,"stem":118,"icon":119},"Live Replay Downloader for Large Streaming Videos","\u002Fdocs\u002Fusecases\u002Flive-replays","1.docs\u002F4.usecases\u002F3.live-replays","i-lucide-radio",{"title":121,"path":122,"stem":123,"icon":124},"Podcast and Audio Downloader for Offline Listening","\u002Fdocs\u002Fusecases\u002Fpodcasts-audio","1.docs\u002F4.usecases\u002F4.podcasts-audio","i-lucide-headphones",{"title":126,"path":127,"stem":128,"icon":53},"Bulk Image Downloader for Web Galleries and Wallpapers","\u002Fdocs\u002Fusecases\u002Fimage-galleries","1.docs\u002F4.usecases\u002F5.image-galleries",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":32},"Troubleshooting","i-lucide-wrench","\u002Fdocs\u002Ftroubleshooting","1.docs\u002F5.troubleshooting",[135,139,144],{"title":136,"path":137,"stem":138,"icon":131},"Common Issues Troubleshooting","\u002Fdocs\u002Ftroubleshooting\u002Fcommon-issues","1.docs\u002F5.troubleshooting\u002F1.common-issues",{"title":140,"path":141,"stem":142,"icon":143},"Known Limitations & Caveats","\u002Fdocs\u002Ftroubleshooting\u002Fknown-issues","1.docs\u002F5.troubleshooting\u002F2.known-issues","i-lucide-alert-triangle",{"title":145,"path":146,"stem":147,"icon":148},"FAQ","\u002Fdocs\u002Ftroubleshooting\u002Ffaq","1.docs\u002F5.troubleshooting\u002F3.faq","i-lucide-message-circle-question",{"title":150,"icon":151,"path":152,"stem":153,"children":154,"page":32},"Developer Docs","i-lucide-code","\u002Fdocs\u002Fdeveloper","1.docs\u002F6.developer",[155,160],{"title":156,"path":157,"stem":158,"icon":159},"Contributing Guide","\u002Fdocs\u002Fdeveloper\u002Fcontributing","1.docs\u002F6.developer\u002F1.contributing","i-lucide-git-pull-request",{"title":161,"path":162,"stem":163,"icon":164},"Project Architecture","\u002Fdocs\u002Fdeveloper\u002Farchitecture","1.docs\u002F6.developer\u002F2.architecture","i-lucide-box",{"title":166,"path":167,"stem":168,"children":169,"page":32},"Zh Hans","\u002Fzh-hans","zh-Hans",[170,189,226,243,268,285],{"title":171,"path":172,"stem":173,"children":174,"icon":32},"快速开始","\u002Fzh-hans\u002Fgetting-started","zh-Hans\u002F1.getting-started\u002F1.index",[175,177,181,185],{"title":176,"path":172,"stem":173,"icon":16},"简介",{"title":178,"path":179,"stem":180,"icon":21},"安装","\u002Fzh-hans\u002Fgetting-started\u002Finstallation","zh-Hans\u002F1.getting-started\u002F2.installation",{"title":182,"path":183,"stem":184,"icon":26},"使用方法","\u002Fzh-hans\u002Fgetting-started\u002Fusage","zh-Hans\u002F1.getting-started\u002F3.usage",{"title":186,"path":187,"stem":188,"icon":31},"配置参考","\u002Fzh-hans\u002Fgetting-started\u002Fconfiguration","zh-Hans\u002F1.getting-started\u002F4.configuration",{"title":190,"icon":35,"path":191,"stem":192,"children":193,"page":32},"功能特性","\u002Fzh-hans\u002Ffeatures","zh-Hans\u002F2.features",[194,198,202,206,210,214,218,222],{"title":195,"path":196,"stem":197,"icon":43},"视频嗅探","\u002Fzh-hans\u002Ffeatures\u002Fvideo-sniffing","zh-Hans\u002F2.features\u002F1.video-sniffing",{"title":199,"path":200,"stem":201,"icon":48},"音频捕获","\u002Fzh-hans\u002Ffeatures\u002Faudio-capture","zh-Hans\u002F2.features\u002F2.audio-capture",{"title":203,"path":204,"stem":205,"icon":53},"图片下载","\u002Fzh-hans\u002Ffeatures\u002Fimage-download","zh-Hans\u002F2.features\u002F3.image-download",{"title":207,"path":208,"stem":209,"icon":58},"隐私与安全","\u002Fzh-hans\u002Ffeatures\u002Fprivacy-security","zh-Hans\u002F2.features\u002F4.privacy-security",{"title":211,"path":212,"stem":213,"icon":63},"格式转换","\u002Fzh-hans\u002Ffeatures\u002Fformat-conversion","zh-Hans\u002F2.features\u002F5.format-conversion",{"title":215,"path":216,"stem":217,"icon":68},"批量下载","\u002Fzh-hans\u002Ffeatures\u002Fbatch-download","zh-Hans\u002F2.features\u002F6.batch-download",{"title":219,"path":220,"stem":221,"icon":73},"键盘快捷键","\u002Fzh-hans\u002Ffeatures\u002Fkeyboard-shortcuts","zh-Hans\u002F2.features\u002F7.keyboard-shortcuts",{"title":223,"path":224,"stem":225,"icon":78},"搜索与筛选","\u002Fzh-hans\u002Ffeatures\u002Fsearch-filter","zh-Hans\u002F2.features\u002F8.search-filter",{"title":227,"icon":81,"path":228,"stem":229,"children":230,"page":32},"高级指南","\u002Fzh-hans\u002Fadvanced","zh-Hans\u002F3.advanced",[231,235,239],{"title":232,"path":233,"stem":234,"icon":89},"在线工具","\u002Fzh-hans\u002Fadvanced\u002Fonline-tools","zh-Hans\u002F3.advanced\u002F1.online-tools",{"title":236,"path":237,"stem":238,"icon":94},"浏览器兼容性","\u002Fzh-hans\u002Fadvanced\u002Fbrowser-compatibility","zh-Hans\u002F3.advanced\u002F2.browser-compatibility",{"title":240,"path":241,"stem":242,"icon":99},"下载引擎架构","\u002Fzh-hans\u002Fadvanced\u002Fdownload-engine","zh-Hans\u002F3.advanced\u002F3.download-engine",{"title":244,"icon":102,"path":245,"stem":246,"children":247,"page":32},"使用场景","\u002Fzh-hans\u002Fusecases","zh-Hans\u002F4.usecases",[248,252,256,260,264],{"title":249,"path":250,"stem":251,"icon":110},"在线课程视频下载与离线学习","\u002Fzh-hans\u002Fusecases\u002Fonline-courses","zh-Hans\u002F4.usecases\u002F1.online-courses",{"title":253,"path":254,"stem":255,"icon":43},"视频平台流媒体下载与素材收集","\u002Fzh-hans\u002Fusecases\u002Fvideo-platforms","zh-Hans\u002F4.usecases\u002F2.video-platforms",{"title":257,"path":258,"stem":259,"icon":119},"直播回放下载与大文件流媒体保存","\u002Fzh-hans\u002Fusecases\u002Flive-replays","zh-Hans\u002F4.usecases\u002F3.live-replays",{"title":261,"path":262,"stem":263,"icon":124},"播客与网页音频下载","\u002Fzh-hans\u002Fusecases\u002Fpodcasts-audio","zh-Hans\u002F4.usecases\u002F4.podcasts-audio",{"title":265,"path":266,"stem":267,"icon":53},"图库与壁纸批量图片下载","\u002Fzh-hans\u002Fusecases\u002Fimage-galleries","zh-Hans\u002F4.usecases\u002F5.image-galleries",{"title":269,"icon":131,"path":270,"stem":271,"children":272,"page":32},"故障排除","\u002Fzh-hans\u002Ftroubleshooting","zh-Hans\u002F5.troubleshooting",[273,277,281],{"title":274,"path":275,"stem":276,"icon":131},"常见问题排查","\u002Fzh-hans\u002Ftroubleshooting\u002Fcommon-issues","zh-Hans\u002F5.troubleshooting\u002F1.common-issues",{"title":278,"path":279,"stem":280,"icon":143},"已知限制与注意事项","\u002Fzh-hans\u002Ftroubleshooting\u002Fknown-issues","zh-Hans\u002F5.troubleshooting\u002F2.known-issues",{"title":282,"path":283,"stem":284,"icon":148},"常见问题解答","\u002Fzh-hans\u002Ftroubleshooting\u002Ffaq","zh-Hans\u002F5.troubleshooting\u002F3.faq",{"title":286,"icon":151,"path":287,"stem":288,"children":289,"page":32},"开发者文档","\u002Fzh-hans\u002Fdeveloper","zh-Hans\u002F6.developer",[290,294],{"title":291,"path":292,"stem":293,"icon":159},"贡献指南","\u002Fzh-hans\u002Fdeveloper\u002Fcontributing","zh-Hans\u002F6.developer\u002F1.contributing",{"title":295,"path":296,"stem":297,"icon":164},"项目架构","\u002Fzh-hans\u002Fdeveloper\u002Farchitecture","zh-Hans\u002F6.developer\u002F2.architecture",{"id":299,"title":161,"body":300,"date":1857,"description":1858,"extension":1859,"lastModified":1860,"meta":1861,"navigation":1862,"path":162,"seo":1863,"stem":163,"__hash__":1866},"docs\u002F1.docs\u002F6.developer\u002F2.architecture.md",{"type":301,"value":302,"toc":1836},"minimark",[303,307,314,317,321,333,344,350,415,430,432,436,441,447,453,458,461,466,536,541,795,807,811,814,818,886,890,1106,1119,1121,1125,1132,1135,1140,1146,1151,1173,1185,1192,1195,1199,1205,1209,1226,1240,1242,1246,1253,1258,1264,1274,1283,1292,1294,1298,1302,1308,1313,1402,1414,1418,1424,1435,1437,1441,1445,1451,1456,1470,1475,1486,1498,1502,1507,1511,1522,1526,1534,1548,1552,1557,1561,1572,1584,1588,1597,1601,1612,1624,1626,1630,1636,1641,1723,1725,1729,1732,1738,1745,1750,1756,1768,1770,1774,1832],[304,305,306],"p",{},"This document is for developers who want to understand FlowPick's internal design in depth, covering system architecture, module responsibilities, data flow, and key design decisions.",[304,308,309],{},[310,311],"img",{"alt":312,"src":313},"System Architecture Overview","\u002Fscreenshots\u002Farchitecture-overview.png",[315,316],"hr",{},[318,319,312],"h2",{"id":320},"system-architecture-overview",[304,322,323,324,328,329,332],{},"FlowPick consists of two main product forms: ",[325,326,327],"strong",{},"Browser Extension"," and ",[325,330,331],{},"Online Tool Website",". Both share the core download engine but differ in media detection and network request handling.",[334,335,340],"pre",{"className":336,"code":338,"language":339},[337],"language-text","┌─────────────────────────────────────────────────────────┐\n│                      FlowPick                           │\n│                                                         │\n│  ┌──────────────────┐    ┌──────────────────────────┐   │\n│  │ Browser Extension │    │   Online Tool Website    │   │\n│  │                  │    │                          │   │\n│  │ · Network request │    │ · M3U8 Downloader       │   │\n│  │   monitoring     │    │ · DASH Downloader       │   │\n│  │ · Auto media      │    │ · Documentation System  │   │\n│  │   detection      │    │ · Homepage              │   │\n│  │ · Popup UI       │    │                          │   │\n│  │ · Cross-origin    │    │                          │   │\n│  │   request ability│    │                          │   │\n│  └────────┬─────────┘    └────────────┬─────────────┘   │\n│           │                           │                 │\n│           └───────────┬───────────────┘                 │\n│                       │                                 │\n│           ┌───────────▼───────────────┐                 │\n│           │     Core Download Engine   │                 │\n│           │                           │                 │\n│           │ · useStreamMerge.ts       │                 │\n│           │ · useFFmpeg.ts            │                 │\n│           │ · Segmented download &    │                 │\n│           │   concurrency control     │                 │\n│           │ · AES-128 decryption      │                 │\n│           │ · Streaming file write    │                 │\n│           │ · Format conversion       │                 │\n│           └───────────────────────────┘                 │\n└─────────────────────────────────────────────────────────┘\n","text",[341,342,338],"code",{"__ignoreMap":343},"",[304,345,346,349],{},[325,347,348],{},"Positioning of Two Product Forms",":",[351,352,353,367],"table",{},[354,355,356],"thead",{},[357,358,359,363,365],"tr",{},[360,361,362],"th",{},"Dimension",[360,364,327],{},[360,366,331],{},[368,369,370,382,393,404],"tbody",{},[357,371,372,376,379],{},[373,374,375],"td",{},"Target users",[373,377,378],{},"Daily high-frequency users",[373,380,381],{},"Occasional users, environments where extension cannot be installed",[357,383,384,387,390],{},[373,385,386],{},"Core advantage",[373,388,389],{},"Auto-detection, one-click download",[373,391,392],{},"No installation needed, cross-platform",[357,394,395,398,401],{},[373,396,397],{},"Technical constraints",[373,399,400],{},"Manifest V3 limitations",[373,402,403],{},"Same-origin policy restrictions",[357,405,406,409,412],{},[373,407,408],{},"Access method",[373,410,411],{},"Click toolbar icon",[373,413,414],{},"Directly visit web URL",[416,417,418],"note",{},[304,419,420,421,425,426,429],{},"For detailed feature differences and selection recommendations between extension and online tools, see ",[422,423,424],"a",{"href":87},"Online Tools — Comparison with Extension",". For extension installation steps, see ",[422,427,428],{"href":19},"Installation Guide",".",[315,431],{},[318,433,435],{"id":434},"module-details","Module Details",[437,438,440],"h3",{"id":439},"core-download-engine","Core Download Engine",[304,442,443,444,429],{},"Download engine consists of two composables located in ",[341,445,446],{},"app\u002Fcomposables\u002F",[304,448,449],{},[310,450],{"alt":451,"src":452},"Core Engine Module Relationships","\u002Fscreenshots\u002Fcore-engine-modules.png",[454,455,457],"h4",{"id":456},"usestreammergets","useStreamMerge.ts",[304,459,460],{},"Responsible for downloading, decrypting, merging, and writing media segments. This is the most core module of the entire system.",[304,462,463,349],{},[325,464,465],{},"Main Responsibilities",[351,467,468,478],{},[354,469,470],{},[357,471,472,475],{},[360,473,474],{},"Feature",[360,476,477],{},"Implementation",[368,479,480,488,496,504,512,520,528],{},[357,481,482,485],{},[373,483,484],{},"Concurrent segment download",[373,486,487],{},"Worker Pool pattern with shared task counter",[357,489,490,493],{},[373,491,492],{},"Retry mechanism",[373,494,495],{},"Exponential backoff, max 3 retries",[357,497,498,501],{},[373,499,500],{},"AES-128 decryption",[373,502,503],{},"Web Crypto API",[357,505,506,509],{},[373,507,508],{},"Segment concatenation",[373,510,511],{},"Binary direct concatenation (TS) or FFmpeg remuxing (MP4)",[357,513,514,517],{},[373,515,516],{},"File writing",[373,518,519],{},"FSA → StreamSaver → Blob three-tier fallback",[357,521,522,525],{},[373,523,524],{},"Progress tracking",[373,526,527],{},"Sliding window speed calculation + ETA estimation",[357,529,530,533],{},[373,531,532],{},"Memory management",[373,534,535],{},"Sampling estimation + threshold check + strategy selection",[304,537,538,349],{},[325,539,540],{},"Exported Interface",[334,542,546],{"className":543,"code":544,"language":545,"meta":343,"style":343},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export interface StreamMergeOptions {\n  segments: ArrayBuffer[] | AsyncGenerator\u003CArrayBuffer>\n  totalSegments: number\n  filename: string\n  outputFormat?: 'mp4' | 'ts'\n  onProgress?: (progress: StreamMergeProgress) => void\n  signal?: AbortSignal\n}\n\nexport interface StreamMergeProgress {\n  phase: 'downloading' | 'merging'\n  percent: number\n  downloadedBytes: number\n  totalBytes: number\n  speed: string\n  eta: string\n}\n","typescript",[341,547,548,569,600,611,622,652,681,692,698,705,716,740,750,760,770,780,790],{"__ignoreMap":343},[549,550,553,557,561,565],"span",{"class":551,"line":552},"line",1,[549,554,556],{"class":555},"s7zQu","export",[549,558,560],{"class":559},"spNyl"," interface",[549,562,564],{"class":563},"sBMFI"," StreamMergeOptions",[549,566,568],{"class":567},"sMK4o"," {\n",[549,570,572,576,578,581,585,588,591,594,597],{"class":551,"line":571},2,[549,573,575],{"class":574},"swJcz","  segments",[549,577,349],{"class":567},[549,579,580],{"class":563}," ArrayBuffer",[549,582,584],{"class":583},"sTEyZ","[] ",[549,586,587],{"class":567},"|",[549,589,590],{"class":563}," AsyncGenerator",[549,592,593],{"class":567},"\u003C",[549,595,596],{"class":563},"ArrayBuffer",[549,598,599],{"class":567},">\n",[549,601,603,606,608],{"class":551,"line":602},3,[549,604,605],{"class":574},"  totalSegments",[549,607,349],{"class":567},[549,609,610],{"class":563}," number\n",[549,612,614,617,619],{"class":551,"line":613},4,[549,615,616],{"class":574},"  filename",[549,618,349],{"class":567},[549,620,621],{"class":563}," string\n",[549,623,625,628,631,634,638,641,644,646,649],{"class":551,"line":624},5,[549,626,627],{"class":574},"  outputFormat",[549,629,630],{"class":567},"?:",[549,632,633],{"class":567}," '",[549,635,637],{"class":636},"sfazB","mp4",[549,639,640],{"class":567},"'",[549,642,643],{"class":567}," |",[549,645,633],{"class":567},[549,647,648],{"class":636},"ts",[549,650,651],{"class":567},"'\n",[549,653,655,658,660,663,667,669,672,675,678],{"class":551,"line":654},6,[549,656,657],{"class":574},"  onProgress",[549,659,630],{"class":567},[549,661,662],{"class":567}," (",[549,664,666],{"class":665},"sHdIc","progress",[549,668,349],{"class":567},[549,670,671],{"class":563}," StreamMergeProgress",[549,673,674],{"class":567},")",[549,676,677],{"class":559}," =>",[549,679,680],{"class":563}," void\n",[549,682,684,687,689],{"class":551,"line":683},7,[549,685,686],{"class":574},"  signal",[549,688,630],{"class":567},[549,690,691],{"class":563}," AbortSignal\n",[549,693,695],{"class":551,"line":694},8,[549,696,697],{"class":567},"}\n",[549,699,701],{"class":551,"line":700},9,[549,702,704],{"emptyLinePlaceholder":703},true,"\n",[549,706,708,710,712,714],{"class":551,"line":707},10,[549,709,556],{"class":555},[549,711,560],{"class":559},[549,713,671],{"class":563},[549,715,568],{"class":567},[549,717,719,722,724,726,729,731,733,735,738],{"class":551,"line":718},11,[549,720,721],{"class":574},"  phase",[549,723,349],{"class":567},[549,725,633],{"class":567},[549,727,728],{"class":636},"downloading",[549,730,640],{"class":567},[549,732,643],{"class":567},[549,734,633],{"class":567},[549,736,737],{"class":636},"merging",[549,739,651],{"class":567},[549,741,743,746,748],{"class":551,"line":742},12,[549,744,745],{"class":574},"  percent",[549,747,349],{"class":567},[549,749,610],{"class":563},[549,751,753,756,758],{"class":551,"line":752},13,[549,754,755],{"class":574},"  downloadedBytes",[549,757,349],{"class":567},[549,759,610],{"class":563},[549,761,763,766,768],{"class":551,"line":762},14,[549,764,765],{"class":574},"  totalBytes",[549,767,349],{"class":567},[549,769,610],{"class":563},[549,771,773,776,778],{"class":551,"line":772},15,[549,774,775],{"class":574},"  speed",[549,777,349],{"class":567},[549,779,621],{"class":563},[549,781,783,786,788],{"class":551,"line":782},16,[549,784,785],{"class":574},"  eta",[549,787,349],{"class":567},[549,789,621],{"class":563},[549,791,793],{"class":551,"line":792},17,[549,794,697],{"class":567},[416,796,797],{},[304,798,799,800,802,803,429],{},"For complete technical implementation of download engine (including concurrency control, retry strategy, memory management, write strategy comparison), see ",[422,801,96],{"href":97},". For three-tier write strategy fallback logic, see ",[422,804,806],{"href":805},"\u002Fdocs\u002Fadvanced\u002Fdownload-engine#strategy-comparison-summary","Download Engine Architecture — Strategy Comparison Summary",[454,808,810],{"id":809},"useffmpegts","useFFmpeg.ts",[304,812,813],{},"Responsible for FFmpeg WASM loading, lifecycle management, and media processing command execution.",[304,815,816,349],{},[325,817,465],{},[351,819,820,828],{},[354,821,822],{},[357,823,824,826],{},[360,825,474],{},[360,827,477],{},[368,829,830,838,852,862,870,878],{},[357,831,832,835],{},[373,833,834],{},"WASM loading",[373,836,837],{},"On-demand loading, supports multithreading\u002Fsingle-thread auto-switching",[357,839,840,843],{},[373,841,842],{},"Multithreading detection",[373,844,845,846,328,849],{},"Check ",[341,847,848],{},"SharedArrayBuffer",[341,850,851],{},"crossOriginIsolated",[357,853,854,857],{},[373,855,856],{},"TS → MP4 remuxing",[373,858,859],{},[341,860,861],{},"ffmpeg -i input.ts -c copy output.mp4",[357,863,864,867],{},[373,865,866],{},"Audio\u002Fvideo merge",[373,868,869],{},"Write to virtual FS separately, execute merge command",[357,871,872,875],{},[373,873,874],{},"FMP4 reassembly",[373,876,877],{},"Handle DASH initialization segments + media segments",[357,879,880,883],{},[373,881,882],{},"Progress callback",[373,884,885],{},"Parse time info from FFmpeg output",[304,887,888,349],{},[325,889,540],{},[334,891,893],{"className":543,"code":892,"language":545,"meta":343,"style":343},"export const useFFmpeg = () => {\n  return {\n    ffmpeg: Ref\u003CFFmpegType | null>\n    loaded: Ref\u003Cboolean>\n    loading: Ref\u003Cboolean>\n    error: Ref\u003Cstring | null>\n    load: () => Promise\u003Cvoid>\n    mergeToMP4: (options: MergeOptions) => Promise\u003CArrayBuffer>\n    mergeAudioVideo: (options: MergeAudioVideoOptions) => Promise\u003CArrayBuffer>\n    mergeFmp4: (options: MergeFmp4Options) => Promise\u003CArrayBuffer>\n  }\n}\n",[341,894,895,915,922,942,960,975,993,1011,1041,1069,1097,1102],{"__ignoreMap":343},[549,896,897,899,902,905,908,911,913],{"class":551,"line":552},[549,898,556],{"class":555},[549,900,901],{"class":559}," const",[549,903,904],{"class":583}," useFFmpeg ",[549,906,907],{"class":567},"=",[549,909,910],{"class":567}," ()",[549,912,677],{"class":559},[549,914,568],{"class":567},[549,916,917,920],{"class":551,"line":571},[549,918,919],{"class":555},"  return",[549,921,568],{"class":567},[549,923,924,927,929,932,934,937,939],{"class":551,"line":602},[549,925,926],{"class":574},"    ffmpeg",[549,928,349],{"class":567},[549,930,931],{"class":583}," Ref",[549,933,593],{"class":567},[549,935,936],{"class":583},"FFmpegType",[549,938,643],{"class":567},[549,940,941],{"class":567}," null>\n",[549,943,944,947,950,953,955,958],{"class":551,"line":613},[549,945,946],{"class":583},"    loaded",[549,948,949],{"class":574},": ",[549,951,952],{"class":583},"Ref",[549,954,593],{"class":567},[549,956,957],{"class":583},"boolean",[549,959,599],{"class":567},[549,961,962,965,967,969,971,973],{"class":551,"line":624},[549,963,964],{"class":583},"    loading",[549,966,949],{"class":574},[549,968,952],{"class":583},[549,970,593],{"class":567},[549,972,957],{"class":583},[549,974,599],{"class":567},[549,976,977,980,982,984,986,989,991],{"class":551,"line":654},[549,978,979],{"class":583},"    error",[549,981,949],{"class":574},[549,983,952],{"class":583},[549,985,593],{"class":567},[549,987,988],{"class":583},"string",[549,990,643],{"class":567},[549,992,941],{"class":567},[549,994,995,998,1000,1003,1005,1008],{"class":551,"line":683},[549,996,997],{"class":583},"    load",[549,999,949],{"class":574},[549,1001,1002],{"class":567},"()",[549,1004,677],{"class":559},[549,1006,1007],{"class":563}," Promise",[549,1009,1010],{"class":567},"\u003Cvoid>\n",[549,1012,1013,1016,1018,1021,1024,1026,1029,1031,1033,1035,1037,1039],{"class":551,"line":694},[549,1014,1015],{"class":583},"    mergeToMP4",[549,1017,949],{"class":574},[549,1019,1020],{"class":567},"(",[549,1022,1023],{"class":665},"options",[549,1025,349],{"class":567},[549,1027,1028],{"class":563}," MergeOptions",[549,1030,674],{"class":567},[549,1032,677],{"class":559},[549,1034,1007],{"class":563},[549,1036,593],{"class":567},[549,1038,596],{"class":583},[549,1040,599],{"class":567},[549,1042,1043,1046,1048,1050,1052,1054,1057,1059,1061,1063,1065,1067],{"class":551,"line":700},[549,1044,1045],{"class":583},"    mergeAudioVideo",[549,1047,949],{"class":574},[549,1049,1020],{"class":567},[549,1051,1023],{"class":665},[549,1053,349],{"class":567},[549,1055,1056],{"class":563}," MergeAudioVideoOptions",[549,1058,674],{"class":567},[549,1060,677],{"class":559},[549,1062,1007],{"class":563},[549,1064,593],{"class":567},[549,1066,596],{"class":583},[549,1068,599],{"class":567},[549,1070,1071,1074,1076,1078,1080,1082,1085,1087,1089,1091,1093,1095],{"class":551,"line":707},[549,1072,1073],{"class":583},"    mergeFmp4",[549,1075,949],{"class":574},[549,1077,1020],{"class":567},[549,1079,1023],{"class":665},[549,1081,349],{"class":567},[549,1083,1084],{"class":563}," MergeFmp4Options",[549,1086,674],{"class":567},[549,1088,677],{"class":559},[549,1090,1007],{"class":563},[549,1092,593],{"class":567},[549,1094,596],{"class":583},[549,1096,599],{"class":567},[549,1098,1099],{"class":551,"line":718},[549,1100,1101],{"class":567},"  }\n",[549,1103,1104],{"class":551,"line":742},[549,1105,697],{"class":567},[416,1107,1108],{},[304,1109,1110,1111,1114,1115,429],{},"For FFmpeg WASM loading flow, multithreading detection, and performance comparison, see ",[422,1112,1113],{"href":61},"Format Conversion — FFmpeg WASM Engine",". For SharedArrayBuffer configuration requirements, see ",[422,1116,1118],{"href":1117},"\u002Fdocs\u002Fadvanced\u002Fbrowser-compatibility#advanced-apis","Browser Compatibility — Advanced APIs",[315,1120],{},[437,1122,1124],{"id":1123},"page-modules","Page Modules",[454,1126,1128,1129,674],{"id":1127},"m3u8-downloader-m3u8-downloadervue","M3U8 Downloader (",[341,1130,1131],{},"m3u8-downloader.vue",[304,1133,1134],{},"Handles HLS streaming protocol download page.",[304,1136,1137,349],{},[325,1138,1139],{},"Processing Flow",[334,1141,1144],{"className":1142,"code":1143,"language":339},[337],"User inputs URL\n    ↓\nfetch M3U8 content\n    ↓\nm3u8-parser parsing\n    ↓\n┌─ Master Playlist? ──→ Show quality list → User selects\n│\n└─ Media Playlist? ──→ Extract segment list\n    ↓\nCheck #EXT-X-KEY (encryption info)\n    ↓\nDownload key file (if present)\n    ↓\nConcurrent segment download + decrypt\n    ↓\nMerge\u002Fremux\n    ↓\nWrite to disk\n",[341,1145,1143],{"__ignoreMap":343},[304,1147,1148,349],{},[325,1149,1150],{},"Key Dependencies",[1152,1153,1154,1161,1167],"ul",{},[1155,1156,1157,1160],"li",{},[341,1158,1159],{},"m3u8-parser",": Parse M3U8 manifest",[1155,1162,1163,1166],{},[341,1164,1165],{},"useStreamMerge",": Segment download & merging",[1155,1168,1169,1172],{},[341,1170,1171],{},"useFFmpeg",": Format conversion",[416,1174,1175],{},[304,1176,1177,1178,1182,1183,429],{},"For difference between HLS Master Playlist and Media Playlist, see ",[422,1179,1181],{"href":1180},"\u002Fdocs\u002Ffeatures\u002Fvideo-sniffing#hlsm3u8-streams","Video Sniffing — HLS Streams",". For how to use M3U8 downloader in online tools, see ",[422,1184,86],{"href":87},[454,1186,1188,1189,674],{"id":1187},"dash-downloader-dash-downloadervue","DASH Downloader (",[341,1190,1191],{},"dash-downloader.vue",[304,1193,1194],{},"Handles DASH streaming protocol download page.",[304,1196,1197,349],{},[325,1198,1139],{},[334,1200,1203],{"className":1201,"code":1202,"language":339},[337],"User inputs URL\n    ↓\nfetch MPD content\n    ↓\nmpd-parser parsing\n    ↓\nCheck ContentProtection (DRM)\n    ↓\nExtract AdaptationSet (video\u002Faudio)\n    ↓\nShow stream list → User selects\n    ↓\nDownload initialization segments (if present)\n    ↓\nConcurrent media segment download + decrypt\n    ↓\nFMP4 reassembly \u002F A\u002FV merge\n    ↓\nWrite to disk\n",[341,1204,1202],{"__ignoreMap":343},[304,1206,1207,349],{},[325,1208,1150],{},[1152,1210,1211,1217,1221],{},[1155,1212,1213,1216],{},[341,1214,1215],{},"mpd-parser",": Parse MPD manifest",[1155,1218,1219,1166],{},[341,1220,1165],{},[1155,1222,1223,1225],{},[341,1224,1171],{},": FMP4 reassembly & A\u002FV merging",[416,1227,1228],{},[304,1229,1230,1231,1235,1236,429],{},"For DASH stream detection principles and ContentProtection handling, see ",[422,1232,1234],{"href":1233},"\u002Fdocs\u002Ffeatures\u002Fvideo-sniffing#dashmpd-streams","Video Sniffing — DASH Streams",". For DRM protected content limitation description, see ",[422,1237,1239],{"href":1238},"\u002Fdocs\u002Ftroubleshooting\u002Fknown-issues#drm-protected-content","Known Limitations — DRM Protected Content",[315,1241],{},[437,1243,1245],{"id":1244},"documentation-system","Documentation System",[304,1247,1248,1249,1252],{},"Built on Nuxt Content v3, documentation stored as Markdown files under ",[341,1250,1251],{},"content\u002F"," directory.",[304,1254,1255,349],{},[325,1256,1257],{},"Directory Structure",[334,1259,1262],{"className":1260,"code":1261,"language":339},[337],"content\u002Fzh-Hans\u002F\n├── 1.docs\u002F                    # Main documentation\n│   ├── 1.getting-started\u002F     # Getting Started\n│   ├── 2.features\u002F            # Features\n│   ├── 3.advanced\u002F            # Advanced Guide\n│   ├── 5.troubleshooting\u002F     # Troubleshooting\n│   └── 6.developer\u002F           # Developer Documentation\n├── 4.changelog\u002F               # Changelog\n└── 6.legal\u002F                   # Legal Terms\n",[341,1263,1261],{"__ignoreMap":343},[304,1265,1266,1269,1270,1273],{},[325,1267,1268],{},"Navigation System",": Each directory's ",[341,1271,1272],{},".navigation.yml"," defines category title and icon. Nuxt Content automatically collects all documents and generates sidebar navigation.",[304,1275,1276,949,1279,1282],{},[325,1277,1278],{},"Document Layout",[341,1280,1281],{},"app\u002Flayouts\u002Fdocs.vue"," provides unified document page layout, including top navigation, sidebar, and content area.",[416,1284,1285],{},[304,1286,1287,1288,429],{},"For documentation writing conventions (Frontmatter, content format, multilingual), see ",[422,1289,1291],{"href":1290},"\u002Fdocs\u002Fdeveloper\u002Fcontributing#documentation-writing-guide","Contributing Guide — Documentation Writing Guide",[315,1293],{},[318,1295,1297],{"id":1296},"data-flow","Data Flow",[437,1299,1301],{"id":1300},"complete-download-flow","Complete Download Flow",[334,1303,1306],{"className":1304,"code":1305,"language":339},[337],"┌─────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐\n│ Get Manifest│ → │Parse Manifest│ → │Download Segments│ → │Merge & Write│\n└─────────┘    └──────────┘    └──────────┘    └──────────┘\n     │              │               │               │\n     ▼              ▼               ▼               ▼\n  fetch()      m3u8-parser    Worker Pool     useStreamMerge\n                mpd-parser    AES-128 decrypt useFFmpeg\n                              fetch() concurrent FSA\u002FSS\u002FBlob\n",[341,1307,1305],{"__ignoreMap":343},[304,1309,1310,349],{},[325,1311,1312],{},"Detailed Description of Each Stage",[351,1314,1315,1334],{},[354,1316,1317],{},[357,1318,1319,1322,1325,1328,1331],{},[360,1320,1321],{},"Stage",[360,1323,1324],{},"Input",[360,1326,1327],{},"Processing",[360,1329,1330],{},"Output",[360,1332,1333],{},"Possible Failure Reasons",[368,1335,1336,1353,1369,1386],{},[357,1337,1338,1341,1344,1347,1350],{},[373,1339,1340],{},"Get Manifest",[373,1342,1343],{},"M3U8\u002FMPD URL",[373,1345,1346],{},"HTTP GET request",[373,1348,1349],{},"Manifest text",[373,1351,1352],{},"Network error, URL expired, 404",[357,1354,1355,1358,1360,1363,1366],{},[373,1356,1357],{},"Parse Manifest",[373,1359,1349],{},[373,1361,1362],{},"m3u8\u002Fmpd-parser parsing",[373,1364,1365],{},"Segment list + metadata",[373,1367,1368],{},"Non-standard format, DRM protection",[357,1370,1371,1374,1377,1380,1383],{},[373,1372,1373],{},"Download Segments",[373,1375,1376],{},"Segment URL list",[373,1378,1379],{},"Worker Pool concurrent download",[373,1381,1382],{},"ArrayBuffer array",[373,1384,1385],{},"CORS, rate limiting, token expired",[357,1387,1388,1391,1393,1396,1399],{},[373,1389,1390],{},"Merge & Write",[373,1392,1382],{},[373,1394,1395],{},"Concatenation\u002Fremuxing + write",[373,1397,1398],{},"Disk file",[373,1400,1401],{},"Insufficient memory, write permission",[416,1403,1404],{},[304,1405,1406,1407,1411,1412,429],{},"For complete data flow of download engine (including error classification and retry mechanism), see ",[422,1408,1410],{"href":1409},"\u002Fdocs\u002Fadvanced\u002Fdownload-engine#full-data-flow-view","Download Engine Architecture — Full Data Flow View",". For troubleshooting methods when each stage fails, see ",[422,1413,136],{"href":137},[437,1415,1417],{"id":1416},"write-strategy-selection-flow","Write Strategy Selection Flow",[334,1419,1422],{"className":1420,"code":1421,"language":339},[337],"Start writing\n    │\n    ▼\nFile System Access API available?\n    │\n    ├── Yes → Use FSA streaming write (optimal)\n    │          · 16MB buffer\n    │          · Supports any size\n    │\n    └── No → StreamSaver available?\n                │\n                ├── Yes → Use StreamSaver streaming write\n                │          · Service Worker proxy\n                │          · Supports large files\n                │\n                └── No → Estimate file size\n                            │\n                            ├── \u003C 1.5GB → Blob mode\n                            │             · Load all into memory\n                            │             · Trigger browser download\n                            │\n                            └── > 1.5GB → Reject download\n                                           · Prompt to switch browser\n",[341,1423,1421],{"__ignoreMap":343},[416,1425,1426],{},[304,1427,1428,1429,1431,1432,429],{},"For detailed comparison of three-tier write strategies (including applicable scenarios and limitations of each), see ",[422,1430,806],{"href":805},". For each browser's support status for FSA API, see ",[422,1433,1434],{"href":92},"Browser Compatibility — Feature Support Matrix",[315,1436],{},[318,1438,1440],{"id":1439},"key-design-decisions","Key Design Decisions",[437,1442,1444],{"id":1443},"why-choose-ffmpeg-wasm-instead-of-server-side-processing","Why Choose FFmpeg WASM Instead of Server-side Processing?",[304,1446,1447,1450],{},[325,1448,1449],{},"Decision",": All media processing completed client-side in browser.",[304,1452,1453,349],{},[325,1454,1455],{},"Reasons",[1152,1457,1458,1461,1464,1467],{},[1155,1459,1460],{},"Privacy protection: User files not uploaded to server",[1155,1462,1463],{},"Zero server cost: No need to maintain transcoding server cluster",[1155,1465,1466],{},"Instant availability: No need to wait for upload and queuing",[1155,1468,1469],{},"Offline capability: Theoretically usable offline in PWA mode",[304,1471,1472,349],{},[325,1473,1474],{},"Trade-offs",[1152,1476,1477,1480,1483],{},[1155,1478,1479],{},"Performance lower than native FFmpeg (~10-20%)",[1155,1481,1482],{},"First load requires downloading WASM files (~8MB)",[1155,1484,1485],{},"Subject to browser memory limitations",[416,1487,1488],{},[304,1489,1490,1491,1495,1496,429],{},"For performance comparison data between FFmpeg WASM and native version, see ",[422,1492,1494],{"href":1493},"\u002Fdocs\u002Ftroubleshooting\u002Fknown-issues#ffmpeg-wasm-performance","Known Limitations — FFmpeg WASM Performance",". For complete privacy protection explanation, see ",[422,1497,55],{"href":56},[437,1499,1501],{"id":1500},"why-use-three-tier-write-fallback-strategy","Why Use Three-Tier Write Fallback Strategy?",[304,1503,1504,1506],{},[325,1505,1449],{},": Priority chain of FSA → StreamSaver → Blob.",[304,1508,1509,349],{},[325,1510,1455],{},[1152,1512,1513,1516,1519],{},[1155,1514,1515],{},"FSA API is optimal solution but only supported by Chrome\u002FEdge",[1155,1517,1518],{},"StreamSaver has wider compatibility but depends on Service Worker",[1155,1520,1521],{},"Blob is fallback solution ensuring all browsers can download",[304,1523,1524,349],{},[325,1525,1474],{},[1152,1527,1528,1531],{},[1155,1529,1530],{},"Need to maintain three sets of write logic",[1155,1532,1533],{},"Fallback behavior may lead to inconsistent user experience",[416,1535,1536],{},[304,1537,1538,1539,1543,1544,429],{},"For detailed implementation of three-tier strategy and fallback trigger conditions, see ",[422,1540,1542],{"href":1541},"\u002Fdocs\u002Fadvanced\u002Fdownload-engine#file-writing-module","Download Engine Architecture — File Writing Module",". For comparison of write capabilities across browsers, see ",[422,1545,1547],{"href":1546},"\u002Fdocs\u002Fadvanced\u002Fbrowser-compatibility#feature-fallback-strategies","Browser Compatibility — Feature Fallback Strategies",[437,1549,1551],{"id":1550},"why-does-concurrent-download-use-worker-pool-instead-of-pre-segmentation","Why Does Concurrent Download Use Worker Pool Instead of Pre-segmentation?",[304,1553,1554,1556],{},[325,1555,1449],{},": Use shared counter + dynamic task assignment.",[304,1558,1559,349],{},[325,1560,1455],{},[1152,1562,1563,1566,1569],{},[1155,1564,1565],{},"When segment sizes are uneven, pre-segmentation causes some Workers to idle",[1155,1567,1568],{},"Shared counter ensures all Workers keep working until task completion",[1155,1570,1571],{},"Simple implementation without complex load balancing logic",[416,1573,1574],{},[304,1575,1576,1577,1581,1582,429],{},"For concurrent control implementation and performance analysis of Worker Pool, see ",[422,1578,1580],{"href":1579},"\u002Fdocs\u002Fadvanced\u002Fdownload-engine#relationship-between-concurrency-and-performance","Download Engine Architecture — Relationship Between Concurrency and Performance",". For concurrency configuration method, see ",[422,1583,28],{"href":29},[437,1585,1587],{"id":1586},"why-do-extension-and-online-tools-share-core-engine","Why Do Extension and Online Tools Share Core Engine?",[304,1589,1590,949,1592,328,1594,1596],{},[325,1591,1449],{},[341,1593,1165],{},[341,1595,1171],{}," as independent composables, not dependent on extension APIs.",[304,1598,1599,349],{},[325,1600,1455],{},[1152,1602,1603,1606,1609],{},[1155,1604,1605],{},"Code reuse, avoid maintaining two sets of download logic",[1155,1607,1608],{},"Online tools can serve as demo and fallback for extension features",[1155,1610,1611],{},"Easy testing: core logic debuggable in regular web environment",[416,1613,1614],{},[304,1615,1616,1617,1621,1622,429],{},"For differences between extension and online tools in CORS handling, see ",[422,1618,1620],{"href":1619},"\u002Fdocs\u002Ftroubleshooting\u002Fknown-issues#cors-cross-origin-restrictions","Known Limitations — CORS Cross-origin Restrictions",". For feature comparison of two product forms, see ",[422,1623,424],{"href":87},[315,1625],{},[318,1627,1629],{"id":1628},"dependency-graph","Dependency Graph",[334,1631,1634],{"className":1632,"code":1633,"language":339},[337],"m3u8-downloader.vue ──────┐\n                          ├──→ useStreamMerge.ts ──→ Web Crypto API\ndash-downloader.vue ──────┤         │                    fetch API\n                          │         ├──→ useFFmpeg.ts ──→ @ffmpeg\u002Fffmpeg\nExtension Popup ──────────┘         │                    @ffmpeg\u002Futil\n                                    ├──→ File System Access API\n                                    ├──→ StreamSaver.js\n                                    └──→ Blob API\n\nDocumentation ──→ @nuxt\u002Fcontent ──→ Markdown Files\n                └──→ @nuxt\u002Fui ──→ Tailwind CSS\n",[341,1635,1633],{"__ignoreMap":343},[304,1637,1638,349],{},[325,1639,1640],{},"Dependency Relationship Explanation",[351,1642,1643,1656],{},[354,1644,1645],{},[357,1646,1647,1650,1653],{},[360,1648,1649],{},"Dependency",[360,1651,1652],{},"Type",[360,1654,1655],{},"Description",[368,1657,1658,1671,1684,1697,1710],{},[357,1659,1660,1665,1668],{},[373,1661,1662],{},[341,1663,1664],{},"useStreamMerge → useFFmpeg",[373,1666,1667],{},"Optional dependency",[373,1669,1670],{},"Only needed for MP4 output or A\u002FV merging",[357,1672,1673,1678,1681],{},[373,1674,1675],{},[341,1676,1677],{},"useStreamMerge → Web Crypto API",[373,1679,1680],{},"Conditional dependency",[373,1682,1683],{},"Only needed for AES-128 encrypted streams",[357,1685,1686,1691,1694],{},[373,1687,1688],{},[341,1689,1690],{},"useStreamMerge → FSA \u002F StreamSaver \u002F Blob",[373,1692,1693],{},"Mutually exclusive selection",[373,1695,1696],{},"Select one write method by priority",[357,1698,1699,1704,1707],{},[373,1700,1701],{},[341,1702,1703],{},"Page → useStreamMerge",[373,1705,1706],{},"Direct dependency",[373,1708,1709],{},"All download pages depend on core engine",[357,1711,1712,1717,1720],{},[373,1713,1714],{},[341,1715,1716],{},"Documentation → @nuxt\u002Fcontent",[373,1718,1719],{},"Framework dependency",[373,1721,1722],{},"Nuxt Content module",[315,1724],{},[318,1726,1728],{"id":1727},"extension-architecture","Extension Architecture",[304,1730,1731],{},"Structure of extension part (not in this repository):",[334,1733,1736],{"className":1734,"code":1735,"language":339},[337],"flowpick-extension\u002F\n├── manifest.json           # Manifest V3 configuration\n├── background\u002F\n│   └── service-worker.js   # Service Worker (network monitoring)\n├── popup\u002F\n│   ├── popup.html          # Popup window\n│   ├── popup.js            # Popup window logic\n│   └── popup.css           # Popup window styles\n├── content\u002F\n│   └── content.js          # Content script (page injection)\n└── assets\u002F\n    └── icons\u002F              # Extension icons\n",[341,1737,1735],{"__ignoreMap":343},[304,1739,1740,1741,1744],{},"Extension monitors network requests via ",[341,1742,1743],{},"webRequest"," API, detects media resources, then sends URL list to popup via message passing. Popup reuses online tool's core download logic.",[304,1746,1747,349],{},[325,1748,1749],{},"Extension Communication Flow",[334,1751,1754],{"className":1752,"code":1753,"language":339},[337],"Content Script ←→ Background Service Worker ←→ Popup UI\n      │                      │                      │\n  Page DOM access        Network request monitor  User interaction UI\n  Media element detect   M3U8\u002FMPD filtering      Download trigger & manage\n",[341,1755,1753],{"__ignoreMap":343},[416,1757,1758],{},[304,1759,1760,1761,1765,1766,429],{},"For Manifest V3 restrictions on extensions and countermeasures, see ",[422,1762,1764],{"href":1763},"\u002Fdocs\u002Ftroubleshooting\u002Fknown-issues#manifest-v3-restrictions","Known Limitations — Manifest V3 Restrictions",". For extension installation and permission explanation, see ",[422,1767,428],{"href":19},[315,1769],{},[318,1771,1773],{"id":1772},"related-documentation","Related Documentation",[1152,1775,1776,1781,1786,1791,1796,1801,1806,1811,1816,1822,1827],{},[1155,1777,1778,1780],{},[422,1779,156],{"href":157}," — Development environment setup, code standards, and PR workflow",[1155,1782,1783,1785],{},[422,1784,96],{"href":97}," — Complete technical implementation of core download engine",[1155,1787,1788,1790],{},[422,1789,40],{"href":41}," — HLS\u002FDASH manifest parsing and encryption detection",[1155,1792,1793,1795],{},[422,1794,60],{"href":61}," — FFmpeg WASM engine and output formats",[1155,1797,1798,1800],{},[422,1799,91],{"href":92}," — Browser API support and degradation strategies",[1155,1802,1803,1805],{},[422,1804,86],{"href":87}," — Online tool usage and limitations",[1155,1807,1808,1810],{},[422,1809,28],{"href":29}," — Concurrency, filter, and other settings",[1155,1812,1813,1815],{},[422,1814,428],{"href":19}," — Extension installation and activation",[1155,1817,1818,1821],{},[422,1819,1820],{"href":141},"Known Limitations"," — Current version technical limitations and edge cases",[1155,1823,1824,1826],{},[422,1825,136],{"href":137}," — Diagnostic tools and troubleshooting steps",[1155,1828,1829,1831],{},[422,1830,55],{"href":56}," — Permission explanation and privacy protection",[1833,1834,1835],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":343,"searchDepth":571,"depth":571,"links":1837},[1838,1839,1844,1848,1854,1855,1856],{"id":320,"depth":571,"text":312},{"id":434,"depth":571,"text":435,"children":1840},[1841,1842,1843],{"id":439,"depth":602,"text":440},{"id":1123,"depth":602,"text":1124},{"id":1244,"depth":602,"text":1245},{"id":1296,"depth":571,"text":1297,"children":1845},[1846,1847],{"id":1300,"depth":602,"text":1301},{"id":1416,"depth":602,"text":1417},{"id":1439,"depth":571,"text":1440,"children":1849},[1850,1851,1852,1853],{"id":1443,"depth":602,"text":1444},{"id":1500,"depth":602,"text":1501},{"id":1550,"depth":602,"text":1551},{"id":1586,"depth":602,"text":1587},{"id":1628,"depth":571,"text":1629},{"id":1727,"depth":571,"text":1728},{"id":1772,"depth":571,"text":1773},"2026-07-08","Technical architecture details of FlowPick, including system design, module breakdown, data flow, and key design decisions.","md","2026-08-17",{},{"icon":164},{"title":1864,"description":1865},"FlowPick Technical Architecture: Media Detection and Stream Merging","Explore the architecture behind FlowPick browser media detection, M3U8\u002FHLS and MPD\u002FDASH parsing, segment downloads, and local merging.","1keMidzk2xu0IUcBtKrWQbjqDbYF_9P-UtymvvqAR5w",[1868,1870],{"title":156,"path":157,"stem":158,"description":1869,"icon":159,"children":-1},"How to contribute code, documentation, or report issues for the FlowPick project.",{"title":176,"path":172,"stem":173,"description":1871,"icon":16,"children":-1},"FlowPick 是一款浏览器端的媒体流嗅探与下载工具，支持 HLS\u002FDASH 流媒体协议，提供扩展和在线工具两种使用方式。",1788792261287]