IPFSとEthereumで構築する改ざん耐性動画配信技術
1. はじめに
急速に進化するWeb3時代において、動画配信プラットフォームの「改ざん耐性」「著作権保護」「分散化」は、従来のサーバー集約型モデルでは実現が難しい課題です。本記事では、Ethereumスマートコントラクトと**IPFS(InterPlanetary File System)**を組み合わせることで、これらの課題を解決する分散型動画ストリーミング基盤の具体的な構築方法を詳説します。
このアプローチにより、
- 動画データの改ざんや消失リスクを根本的に軽減
- 著作権情報や利用ルールの自動執行
- 中央管理者不要の透明性・耐障害性の高いシステム
が実現可能となります。
本記事の実装ガイドでは、「IPFSで動画ファイルを分散保存し、Ethereum上でメタデータと著作権管理をスマートコントラクトで自動化」する具体的な手順を、中級~上級開発者がすぐに活用できる完全なコード例と共に解説します。さらに、実運用で生じる課題への対処法、ベストプラクティス、他技術との比較まで踏み込み、単なる理論に留まらず、実務で役立つノウハウを提供します。
参考資料:
2. 基礎解説:アーキテクチャと技術スタック
2.1 主要な概念
-
IPFS:
コンテンツアドレス型の分散ファイルシステム。ファイルはネットワーク全体に分散して保存され、ハッシュ値(CID)で一意に参照されるため、改ざん耐性が高い。 -
Ethereumスマートコントラクト:
不特定多数で共有される分散台帳上に、プログラム可能な管理・取引ルール(著作権、アクセス権)を記述可能。誰でも検証でき、改ざん不可。
2.2 アーキテクチャ図
+----------------+ +---------------------+ +----------------------+
| 動画アップ主 | (1) | IPFS Network | (2) | Ethereum Blockchain |
+----------------+ -----> +---------------------+ <----> +----------------------+
| (3) | (4) | (5)
V V V
動画ファイルをIPFSへ CID(ハッシュ)取得 CID/著作権情報を
アップロード & 分散保存 スマートコントラクト登録
(1): 動画ファイルのアップロード
(2): IPFSネットワークが動画ファイルを分散保存
(3): IPFSが返すCID(コンテンツID)を取得
(4): CID・著作権メタデータをEthereumスマートコントラクトへ登録
(5): スマートコントラクトにより改ざん耐性のある管理/配信を実現
2.3 技術スタック
- バックエンド: Node.js, ethers.js, ipfs-http-client
- スマートコントラクト: Solidity (>=0.8.0)
- フロントエンド: React, web3.js or ethers.js
- 開発環境: Hardhat (スマートコントラクト開発), Ganache (ローカルEthereumノード)
- インフラ: Infura (Ethereum RPC/API), Pinata or web3.storage (IPFSピン止めサービス)
参考資料:
3. 実践的実装ガイド
3.1 環境準備とセットアップ
動作確認済みバージョン例:
- Node.js: v18.x
- Solidity: ^0.8.21
- ipfs-http-client: ^62.0.0
- ethers: ^6.7.0
- Hardhat: ^2.18.0
# 1. プロジェクト初期化
mkdir ipfs-eth-video-platform && cd $_
npm init -y
# 2. 依存パッケージインストール
npm install --save ethers hardhat ipfs-http-client dotenv
# 3. Hardhatプロジェクトセットアップ
npx hardhat
# (→ "Create a basic sample project" を選択)
# 4. .env 作成(Ethereumノード/Infura/Pinata等のAPIキー管理用)
cp .env.example .env
参考資料:
3.2 基本的な機能の実装
3.2.1 動画ファイルのIPFSアップロード
uploadToIPFS.js
const { create } = require('ipfs-http-client');
require('dotenv').config();
const ipfs = create({
url: process.env.IPFS_API_URL || 'https://ipfs.infura.io:5001/api/v0',
});
async function uploadVideo(filePath) {
const fs = require('fs');
const file = fs.readFileSync(filePath);
const { cid } = await ipfs.add({ content: file });
console.log('アップロード完了 CID:', cid.toString());
return cid.toString();
}
// 使い方
// uploadVideo('./sample.mp4');
module.exports = uploadVideo;
-
.env
にIPFS_API_URL
やAPIキーを設定 - 返却される
cid
が動画ファイルの「改ざん耐性付きアドレス」となる
3.2.2 著作権管理用スマートコントラクト(Solidity)
contracts/VideoCopyright.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract VideoCopyright {
struct Video {
address owner;
string ipfsHash;
string title;
uint256 uploadTime;
string copyrightNote;
}
mapping(string => Video) public videos; // ipfsHash => Video
event VideoRegistered(address indexed owner, string ipfsHash, string title);
function registerVideo(
string memory _ipfsHash,
string memory _title,
string memory _copyrightNote
) external {
require(bytes(videos[_ipfsHash].ipfsHash).length == 0, "既に登録済み");
videos[_ipfsHash] = Video({
owner: msg.sender,
ipfsHash: _ipfsHash,
title: _title,
uploadTime: block.timestamp,
copyrightNote: _copyrightNote
});
emit VideoRegistered(msg.sender, _ipfsHash, _title);
}
function getVideo(string memory _ipfsHash) external view returns (Video memory) {
require(bytes(videos[_ipfsHash].ipfsHash).length != 0, "未登録");
return videos[_ipfsHash];
}
}
3.2.3 スマートコントラクトのデプロイ&連携
deploy.js
const hre = require("hardhat");
async function main() {
const VideoCopyright = await hre.ethers.getContractFactory("VideoCopyright");
const videoCopyright = await VideoCopyright.deploy();
await videoCopyright.deployed();
console.log("VideoCopyrightコントラクト:", videoCopyright.address);
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
-
npx hardhat run scripts/deploy.js --network <network名>
でデプロイ - デプロイ済みアドレスを
.env
に保存
3.2.4 スマートコントラクト登録スクリプト
registerVideo.js
const { ethers } = require("hardhat");
const uploadVideo = require("./uploadToIPFS");
require('dotenv').config();
async function main() {
const [deployer] = await ethers.getSigners();
const contractAddress = process.env.CONTRACT_ADDRESS;
const VideoCopyright = await ethers.getContractFactory("VideoCopyright");
const videoCopyright = VideoCopyright.attach(contractAddress);
// 1. 動画ファイルをIPFSへアップロード
const ipfsHash = await uploadVideo('./sample.mp4');
// 2. スマートコントラクトに登録
const tx = await videoCopyright.registerVideo(
ipfsHash,
"サンプル動画タイトル",
"著作権: 2024 Example User"
);
await tx.wait();
console.log("スマートコントラクト登録完了:", ipfsHash);
}
main();
参考資料:
3.3 応用的な機能の実装
3.3.1 視聴権限制御(NFTベースのアクセスコントロール)
スマートコントラクトにERC721(簡易NFT)を組み合わせ、特定ユーザーのみに視聴権限を付与可能。
contracts/VideoAccessNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract VideoAccessNFT is ERC721 {
uint256 private _tokenId;
mapping(uint256 => string) private _videoHash;
constructor() ERC721("VideoAccessNFT", "VANFT") {}
function mint(address to, string memory ipfsHash) external returns (uint256) {
_tokenId++;
_mint(to, _tokenId);
_videoHash[_tokenId] = ipfsHash;
return _tokenId;
}
function videoHashOf(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId), "不存在");
return _videoHash[tokenId];
}
}
OpenZeppelinの
@openzeppelin/contracts
をnpm install @openzeppelin/contracts
で事前インストール
3.3.2 フロントエンドでの動画再生(React + IPFS)
VideoPlayer.jsx
import React, { useState } from "react";
function VideoPlayer({ ipfsHash }) {
const src = `https://ipfs.io/ipfs/${ipfsHash}`;
return (
<video controls width="600">
<source src={src} type="video/mp4" />
お使いのブラウザはvideoタグに対応していません
</video>
);
}
// 使い方例: <VideoPlayer ipfsHash="Qm..." />
export default VideoPlayer;
参考資料:
4. Tips & ベストプラクティス
-
IPFSへのアップロード時はPinningサービス必須
→ Pinataやweb3.storageでピン止めし、動画データの永続性を担保する
Pinata, web3.storage -
スマートコントラクトの関数は適切に
view
/pure
/external
指定
→ 読み取り専用関数はview
にすることでガス消費を削減 -
動画ファイルは事前に圧縮・最適化
→ IPFSネットワーク負荷とストレージコストを抑制。ffmpeg等でエンコード推奨
ffmpeg -
メタデータの一貫性管理
→ スマートコントラクトへの登録とIPFS上のメタデータ(JSON)を同期して管理 -
フロントエンド/バックエンド間の署名認証強化
→ EIP-712署名やMetaMask連携でなりすまし・不正アップロード防止
EIP-712
5. 詳細な考察
メリ
自動レビュー結果 (2025-08-13 00:52)
- 記事品質: 4.3/5.0
- トピック多様性: 5.0/5.0
- コードサンプル: 4.2/5.0
- 実用性・応用性: 3.0/5.0
- 総合評価: 4.2/5.0 (良好)
- 改善提案: より実践的な応用例や実装パターンを追加することを検討してください
Discussion