Webページがファイルを渡してくれるまでに、実際に起きていること
動画は見えている。まさにその場で、Webブラウザの中で再生されている。それなのに、なぜ保存する方法がないのか。答えはこうです。Webページはファイルそのものを渡すことはめったになく、渡しているのは「組み立て方の指示」であり、ブラウザがそこから組み立てるものは1つのファイルとして存在すらしていないことがあるからです。
FoxDL ページが動画を配信する4つの方法、ファイルなのはそのうち1つだけ
最も古く単純なのは直接ファイルです。ページが.mp4で終わるアドレスを指し示し、ブラウザがそれを取得します。そのアドレスさえ見つかれば、ファイルは手に入ります。小規模なサイト、フォーラム、ニュースサイト、ファイルホスティングの多くは今でもこの方式です。
2つ目はアダプティブストリーミング——HLSやDASHです。ページは数百の短いセグメントを複数の画質レベルで並べたプレイリストを読み込み、プレーヤーがそれを順につなぎ合わせながら、接続状況に応じて画質を切り替えます。見つけるべき単一のファイルは存在しません。保存するには、すべてのセグメントを取得してファイルを組み立て直す必要があります。
3つ目はBlob URLです。ページはすでにJavaScriptでデータを取得しており、ブラウザ自身のメモリ上にある何かへの参照をプレーヤーに渡しています。見えるアドレス(blob:https://…)は、そのページとそのセッションの外では何の意味も持ちません——開くことも、共有することも、ダウンロードすることもできず、たいていの素朴な「動画検出ツール」はここでつまずきます。
4つ目は保護されたコンテンツです。DRMシステムを通じて再生される暗号化セグメントで、復号鍵はコピーの保持を明示的に禁じる条件のもとでブラウザに発行されます。これは回避すべき障害物ではなく、ライセンス契約そのものを成り立たせている仕組みであり、正規のツールがこれを打ち破ることはありません。
Webブラウザが「保存できるもの」に気づく仕組み
見つけたものを保存できるアプリ内ブラウザは、実は複数の仕事を同時にこなしています。それぞれが、他の方法では見逃すケースを拾っています。
- ページのメディア要素を読む
- ドキュメント内の
<video>、<audio>、<source>タグをたどり、そのアドレスを読み取ります。直接ファイルのケースはすぐに拾えますが、ページ読み込み後にJavaScriptが組み立てたものはすべて見逃します。 - シャドウDOMの内側を覗く
- 最近のプレーヤーはカスタム要素として作られており、内部は意図的にページから隔離されています。通常のドキュメントだけを見る検索では、動画があるはずの場所に空の箱しか見えません。
- ページが実際にリクエストしたものを監視する
- ブラウザはページが取得したすべてのリソースを把握しています。どのスクリプトがいつ要求したものであっても、読み込まれたメディアファイルはここに現れます。見える範囲のページ内に、それを指すものが何もなくてもです。
- レスポンスの種類を確認する
.phpで終わるURLが動画を返すこともあれば、.mp4で終わるURLがエラーページを返すこともあります。サーバーが実際に送ってきたContent-Typeだけが本当のことを教えてくれます。拡張子はあくまで推測にすぎません。
ページからの保存がうまくいくときの流れ
順番が重要です。ほとんどの失敗は2番目の手順を飛ばして、ログインページを4ギガバイトぶん転送し始めてしまうことから起こります。
-
まずメディアを数秒再生する
再生が始まるまで何も読み込まないページは多くあります。2秒再生するかどうかが、候補リストが空になるか埋まるかの分かれ目になることがよくあります。
-
候補の正体を確認する
取り込む前に、表示されているサイズと種類を確認します。14KBの「映画」はHTMLページです。
video/mp4を期待していたのにtext/htmlと表示されたら、リンクを間違えています。 -
希望の画質を選ぶ
たいていのストリームは複数の画質を用意しています。スマホでは、最高画質が必ずしも正解とは限りません。違いが見えないのに、ストレージだけは確実に消費するからです。
-
セッション情報を引き継がせる
保護されたリンクは、誰がリクエストしているかを確認します——ログイン済みセッションのCookie、参照元のページ、時にはブラウザの識別情報まで。これらを伴わないダウンロードは、ページ上では問題なく再生できても403エラーになります。
-
届いたものを確認する
開いてみましょう。2秒で止まってしまうファイルは途中で切れており——たいていリンクの期限切れが原因です——そのまま保持するより、やり直す価値があります。
アプリ内Webブラウザが正しくこなすべきこと
メディアを見つけること以外にも、ダウンロードが実際に完了するかどうかを左右する要素があります。
- セッションをダウンロードまで引き継ぐ
Cookie、リファラー、ユーザーエージェントはリクエストと一緒に運ばれる必要があります。これらがなければ、保護されたリンクはページ上では解決できてもダウンローダーでは失敗します。
- その認証情報を保存しない
セッションCookieは、セッションが有効な間はパスワードと同じ価値を持ちます。転送している間だけメモリ上に存在すべきで、データベースにもログにも決して残してはいけません。
- リンクを他のアプリに渡さない
iOSは、あるドメインを扱うと宣言しているアプリがあれば、タップされたリンクを喜んでそちらへ渡してしまいます。メディア保存を目的としたWebブラウザは、その遷移を自ら取り消して発行し直す必要があります。そうしないと、目当てのページは他人のアプリの中へ消えてしまいます。
- 描画前にページを軽くする
コンテンツブロッカーはここでは広告対策だけの話ではありません。トラッカーやオーバーレイが減るということは、メディア一覧に紛れ込む偽の候補も減るということです。
- 動画だけでなく文書も扱う
PDF、ZIP、Office文書は、人々がWebから保存するもののもう半分であり、それらも他のすべてと同じライブラリに収まるべきです。
よくある質問
なぜSafari単体ではこれができないのですか?
Safariはファイルのダウンロード自体は行います——iOS 13以降ずっとそうです。できないのは、リンクではなくストリーミングとして配信されているメディアをページの中から探し出すことと、セグメント化されたストリームを1つのファイルに組み立て直すことです。Safariはあくまでブラウザであり、その作業はダウンロードマネージャーの領分です。
Blob URLとは何で、なぜダウンロードできないのですか?
それは、ページがすでにメモリ上に保持しているデータへのハンドルです。そのタブの外では存在自体がないため、どこかに貼り付けても何も出てきません。元となるメディアはどこか実在する場所から取得されており、探す価値があるのはBlobではなくそのアドレスのほうです。
ページ上では問題なく再生されるのに、ダウンロードが403になるのはなぜですか?
ダウンロードのリクエストに、ページが持っていたもの——セッションCookie、参照元ページ、時にはブラウザの識別情報の一致——が伴っていなかったからです。サーバーはまさにこの組み合わせを使って、閲覧者とスクレイパーを区別しています。
何でも保存できますか?
できません。それは意図的な設計です。DRMで保護されたコンテンツは、保持を禁じるライセンスのもとで発行された鍵で暗号化されています。セグメントごとに短時間だけ有効なトークンで個別に署名しているサイトもあります。どちらも設計どおりに機能しています。
FoxDL内蔵のWebブラウザ
タブ機能を備えた普通のWebブラウザですが、その役割は日常のブラウジングではなく、ライブラリへ取り込むことです。
- 6系統の検出を組み合わせており、シャドウDOMやページが実際にリクエストした記録も含むため、JavaScriptだけで作られたプレーヤーでも見つけ出せます。
- 実際の種類はレスポンスから判定され、拡張子からの推測には頼りません。取得できない
blob:の候補は、提示して失敗させるのではなく最初から除外されます。 - Cookie、リファラー、ユーザーエージェントはダウンロードまで引き継がれ、保護されたリンクも解決できます。これらがディスクに書き込まれることは一切ありません。
- コンテンツブロッカーが描画前にページを軽くします。
- PDF、ZIP、文書もメディアと同じライブラリへワンタップで保存できます。
- タブ、ブックマーク、自分だけのショートカットを並べたスタートページ。
FoxDLは独自のコンテンツを一切提供しません。保存するものは自分が持ち込んだものであり、それを保持する権利があるかどうかはあなた自身の責任です。
よくある質問
- Webページからファイルをダウンロードするにはどうすればいいですか?
- FoxDLはHLS(m3u8)ストリームをダウンロードできますか?
- アプリを終了してもダウンロードは続きますか?
- FoxDLはIPTVチャンネルや映画、ストリームを提供していますか?