IPFSとEthereumで構築する動画権利自動管理システム
IPFSとEthereumで構築する動画権利自動管理システム
1. はじめに
分散型ウェブ(Web3)への関心が高まるなか、動画配信プラットフォームも中央集権的な仕組みから分散型アーキテクチャへと進化しています。本記事では「EthereumスマートコントラクトとIPFSを活用した権利管理付き分散型動画配信プラットフォームの開発」をテーマに、実用的かつ応用可能な権利管理システムの構築手法を解説します。
既存の動画サービスでは、著作権管理や収益分配の透明性、改ざん耐性などに課題が残っています。こうした問題を解決するために、本記事ではIPFS(InterPlanetary File System)による耐改ざん性の高い動画保存と、Ethereumスマートコントラクトによる動画権利管理・収益分配自動化の連携を中心に据えます。
ターゲット読者は個人開発者であり、実際に手を動かして「動くもの」を作りたい人です。本記事を読むことで、以下のような具体的メリットが得られます。
- 動画データの分散保存とオンチェーン権利管理の連携による実装ノウハウ
- スマートコントラクトとIPFSをシームレスに統合する具体的なコード例
- 開発効率・セキュリティ・拡張性を意識した設計・実装パターン
参考資料
2. 基礎: システムアーキテクチャと主要技術
アーキテクチャ概要
+------------------+ +----------------+ +-------------------+
| 動画アップローダ |---->| IPFSノード |----->| 分散動画ストレージ |
+------------------+ +----------------+ +-------------------+
| | ^
v | |
+------------------+ | +------------------+
| Ethereum契約管理 |<------------+----------------| 視聴者/購入者 |
+------------------+ +------------------+
- 動画ファイルはIPFSにアップロードされ、**コンテンツアドレス(CID)**が生成される。
- CIDやメタデータをEthereumスマートコントラクトで管理し、権利・所有関係・課金制御もコントラクトで担保。
- ユーザーはスマートコントラクト経由で視聴権限や収益分配のトランザクションを実行。
技術スタック
- IPFS: 大容量ファイルを分散保存・配信。改ざん耐性があり、中央障害点なし。
- Ethereum(Solidity): スマートコントラクトで所有権・権利管理・収益分配ロジック実装。
- Node.js / TypeScript: バックエンド・バッチ処理・API用。
- Web3.js or Ethers.js: フロント/バックエンドからEthereumと連携。
- React (Next.js): フロントエンドUI(今回は重点外)。
参考資料
3. 実践的実装ガイド
3.1. 環境準備とセットアップ
バージョン指定
- Node.js v18.x
- npm v9.x
- Solidity ^0.8.20
- Hardhat ^2.17.0
- ipfs-http-client ^60.x
- ethers.js ^6.x
インストール
# プロジェクト初期化
mkdir ipfs-eth-video-rights && cd ipfs-eth-video-rights
npm init -y
# 必要パッケージ
npm install --save hardhat @nomiclabs/hardhat-ethers ethers ipfs-http-client dotenv
npx hardhat
# Solidityプロジェクト初期化
# "Create a basic sample project" を選択
ローカルIPFSノード起動
# IPFSのインストール(未導入なら)
npm install -g ipfs
# ローカルノード起動
ipfs init
ipfs daemon
参考資料
3.2. 基本的な機能の実装
1. IPFSへの動画ファイルアップロード(Node.js)
uploadToIpfs.js
:
const { create } = require('ipfs-http-client');
const fs = require('fs');
const ipfs = create({ url: 'http://localhost:5001' }); // ローカルIPFS
async function uploadVideo(filePath) {
const file = fs.readFileSync(filePath);
const { cid } = await ipfs.add({ content: file });
console.log(`動画CID: ${cid.toString()}`);
return cid.toString();
}
// 使い方: node uploadToIpfs.js ./sample.mp4
if (require.main === module) {
const filePath = process.argv[2];
uploadVideo(filePath);
}
2. Ethereumスマートコントラクトで動画メタデータと権利管理
contracts/VideoRights.sol
:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract VideoRights {
struct Video {
address owner;
string ipfsCid;
uint256 price;
mapping(address => bool) viewers;
}
mapping(uint256 => Video) public videos;
uint256 public videoCount;
event VideoUploaded(uint256 indexed videoId, address indexed owner, string ipfsCid, uint256 price);
function uploadVideo(string memory _ipfsCid, uint256 _price) external {
Video storage v = videos[videoCount];
v.owner = msg.sender;
v.ipfsCid = _ipfsCid;
v.price = _price;
emit VideoUploaded(videoCount, msg.sender, _ipfsCid, _price);
videoCount++;
}
function buyViewRight(uint256 _videoId) external payable {
Video storage v = videos[_videoId];
require(msg.value >= v.price, "Not enough ETH");
v.viewers[msg.sender] = true;
payable(v.owner).transfer(msg.value);
}
function canView(uint256 _videoId, address _user) external view returns (bool) {
return videos[_videoId].viewers[_user];
}
function getIpfsCid(uint256 _videoId) external view returns (string memory) {
return videos[_videoId].ipfsCid;
}
}
3. スマートコントラクトのデプロイ
scripts/deploy.js
:
const hre = require("hardhat");
async function main() {
const VideoRights = await hre.ethers.getContractFactory("VideoRights");
const contract = await VideoRights.deploy();
await contract.waitForDeployment();
console.log(`Deployed to: ${contract.target}`);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
npx hardhat node
npx hardhat run scripts/deploy.js --network localhost
参考資料
3.3. 応用的な機能の実装
動画のNFT化と二次流通・ロイヤリティ対応
contracts/VideoNFT.sol
:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract VideoNFT is ERC721, Ownable {
uint256 public nextTokenId;
mapping(uint256 => string) public tokenIpfsCid;
uint256 public royaltyFee = 500; // 5% (500 basis points)
address public royaltyRecipient;
constructor() ERC721("VideoNFT", "VNFT") {
royaltyRecipient = msg.sender;
}
function mint(address to, string memory ipfsCid) external onlyOwner {
uint256 tokenId = nextTokenId++;
_safeMint(to, tokenId);
tokenIpfsCid[tokenId] = ipfsCid;
}
function setRoyaltyRecipient(address recipient) external onlyOwner {
royaltyRecipient = recipient;
}
function royaltyInfo(uint256, uint256 salePrice) external view returns (address, uint256) {
return (royaltyRecipient, (salePrice * royaltyFee) / 10000);
}
}
ERC721Aなどによる大量発行最適化 or 動画アクセス制御
- OpenZeppelinのAccessControlやMerkleProofで、限定公開やホワイトリスト視聴権限も実装可能。
参考資料
4. Tips & ベストプラクティス
-
メタデータ管理はJSONで設計
動画タイトル、説明、サムネイルCID等もIPFS上でJSON配信し、スマートコントラクトからURI参照。 -
スマートコントラクトのアップグレード性確保
UUPSやProxyパターンを意識し、将来的な機能追加も容易に。 -
大容量動画のアップロードはChunk化推奨
IPFSのadd
で大きすぎるファイルはチャンク分割を明示的に指定。 -
アクセス制御はオフチェーン・オンチェーンのハイブリッド設計を検討
オンチェーンは「権利の証明」だけにし、実際のストリームアクセスは署名検証等で簡易的に。 -
テストネットで十分に検証
Polygon MumbaiやGoerli等でガスコストやスケーラビリティも事前評価。
参考資料
5. 詳細な考察: 他手法との比較・将来性
メリット
- 中央障害点を排除: サーバーダウンや運営停止の影響なし
- 権利管理・収益分配の透明性と自動化: 改ざん不能、トラストレスな収益送金が可能
- 2次流通やロイヤリティの自動化: NFT連携による新しい収益モデル
デメリット
- ガスコストとスケーラビリティ課題: Ethereum本体は高コスト。L2利用やサイドチェーン検討が必要
- オフチェーン部分の脆弱性: IPFSだけでは「誰でも閲覧可」となるため、実用では追加の暗号化やアクセストークン管理が必要
- 動画再生UXの難しさ: IPFS経由の動画はCDNに比べ初回遅延が大きい
他技術との比較
-
従来型クラウド(例: AWS S3 + DRM)
→ 強固なアクセス制御・高速配信・スケーラビリティは優れるが、中央集権的で透明性が低い。 -
分散ストレージ(例: Filecoin, Arweave)
→ IPFSより長期保存やインセンティブ設計に強み。Filecoinと連携も可。 -
専用NFTマーケットプレイス
→ NFTによる権利流通は容易だが、動画データまで一体で管理するには追加設計が必須。
将来性
- L2・L3やZero-Knowledge Proof、暗号化ストリーミング等の進展により、より実用的な分散型動画配信が現実味。
- 独自トークンやDAOと組み合わせた次世代クリエイターエコノミーの基盤としても
自動レビュー結果 (2025-08-17 00:55)
- 記事品質: 4.5/5.0
- トピック多様性: 5.0/5.0
- コードサンプル: 4.2/5.0
- 実用性・応用性: 3.7/5.0
- 総合評価: 4.4/5.0 (良好)
Discussion