{"id":28513427,"url":"https://github.com/livepeer/video-nft-sample","last_synced_at":"2025-07-04T06:30:40.978Z","repository":{"id":39707118,"uuid":"481465752","full_name":"livepeer/video-nft-sample","owner":"livepeer","description":null,"archived":false,"fork":false,"pushed_at":"2022-09-29T18:23:24.000Z","size":46,"stargazers_count":3,"open_issues_count":0,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-30T02:49:06.545Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"video-nft-sample.vercel.app","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/livepeer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-04-14T04:30:36.000Z","updated_at":"2022-08-23T20:26:47.000Z","dependencies_parsed_at":"2022-08-24T01:31:13.181Z","dependency_job_id":null,"html_url":"https://github.com/livepeer/video-nft-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/livepeer/video-nft-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/livepeer%2Fvideo-nft-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/livepeer%2Fvideo-nft-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/livepeer%2Fvideo-nft-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/livepeer%2Fvideo-nft-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/livepeer","download_url":"https://codeload.github.com/livepeer/video-nft-sample/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/livepeer%2Fvideo-nft-sample/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263461282,"owners_count":23470088,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-09T01:07:03.118Z","updated_at":"2025-07-04T06:30:40.966Z","avatar_url":"https://github.com/livepeer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Video NFT Sample\n\n## Step 0. Installations\n\n```bash\nmkdir video-nft-sample\ncd video-nft-sample\nnpm install init\n```\n\n### npm\n```bash\nnpm install --save dotenv express http-proxy-middleware\n```\n\nor \n\n### yarn \n```bash\nyarn add dotenv express http-proxy-middleware\n```\n\n\n## Step 1. Create an index.js \n\nMake an index.js for an express server to run a proxy. \n\n* Barebone Express App forwards the calls to the Livepeer API whilst injecting an API key: \n\n* Make sure you have your API in your `.env` file \n\nCode below is express server :\n```js\nconst express = require('express');\nconst { createProxyMiddleware } = require('http-proxy-middleware');\nconst path = require('path');\nconst app = express();\nrequire('dotenv').config();\nconst PORT = process.env.PORT || 3000;\nconst proxy = createProxyMiddleware({\n    target: 'https://livepeer.com',\n    changeOrigin: true,\n    headers: {\n        authorization:  `Bearer  ${process.env.LP_API_KEY}`\n    }\n});\n\n\napp.use('/js',express.static(path.join(__dirname, 'public/js')));\n\n\napp.get('/', function(req, res) {\n    res.sendFile(path.join(__dirname, '/public/index.html'));\n  });\napp.get('/api/asset/:id', proxy);\napp.get('/api/task/:id', proxy);\napp.post('/api/asset/request-upload', proxy);\napp.post('/api/asset/transcode', proxy);\napp.post('/api/asset/:id/export', proxy);\n\n\napp.listen(PORT);\n```\n\n## Step 2. Make a **index.html** adding video-nft cdn \n\n* The index.html will contain ethers.js, video-nft sdk and tailwind.css\n\n* tailwind.css to style the app \n* ether.js to connet metamask wallet \n* video-nft to mint the video being uploadedx\n\n```html\n\u003c!DOCTYPE html\u003e\n\n\u003chtml lang=\"en\"\u003e\n\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n    \u003cscript src=\"https://cdn.ethers.io/lib/ethers-5.2.umd.min.js\" type=\"application/javascript\"\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/@livepeer/video-nft@0.3.2/dist/index.umd.js\"\u003e\u003c/script\u003e\n        \u003cscript src=\"https://cdn.tailwindcss.com\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n   \u003c!-- Code for Sample App --\u003e\n\u003c/body\u003e\n\n\u003cscript type=\"text/javascript\" src=\"/js/ui.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"/js/sdk.js\"\u003e\u003c/script\u003e\n\u003c/html\u003e\n```\n\n\n## Step 3.  Adding the logic for ui.js \n\nThe code implements the user interface in javascript this logic helps  user to drag and drop the video to the uploader displaying a progress bar.  \n\n```javascript\nlet dropArea = document.getElementById(\"drop-area\");\nconst videoSrc = document.querySelector(\"#video-source\");\nconst videoTag = document.querySelector(\"#video-tag\");\n\n// Prevent default drag behaviors\n;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName =\u003e {\n    dropArea.addEventListener(eventName, preventDefaults, false)\n    document.body.addEventListener(eventName, preventDefaults, false)\n});\n\n\n// Highlight drop area when item is dragged over it\n['dragenter', 'dragover'].forEach(eventName =\u003e {\n    dropArea.addEventListener(eventName, highlight, false)\n});\n\n['dragleave', 'drop'].forEach(eventName =\u003e {\n    dropArea.addEventListener(eventName, unhighlight, false)\n});\n\nfunction highlight(e) {\n\n    dropArea.classList.add('outline-[#00eb88]')\n}\n\nfunction unhighlight(e) {\n    dropArea.classList.remove('outline-[#00eb88]')\n}\n\ndropArea.addEventListener('drop', handleDrop, false)\n\nfunction preventDefaults(e) {\n    e.preventDefault()\n    e.stopPropagation()\n}\n\nfunction handleDrop(e) {\n    var dt = e.dataTransfer\n    var files = dt.files\n\n    handleFiles(files)\n}\n\nlet uploadProgress = []\nlet progressBar = document.getElementById('progress-bar')\n\nfunction initializeProgress(numFiles) {\n    progressBar.style.width = \"0%\";\n    uploadProgress = []\n\n    for (let i = numFiles; i \u003e 0; i--) {\n        uploadProgress.push(0)\n    }\n}\n\nfunction updateProgress(fileNumber, percent) {\n    uploadProgress[fileNumber] = percent\n    let total = uploadProgress.reduce((tot, curr) =\u003e tot + curr, 0) / uploadProgress.length\n    progressBar.style.width = `${total}%`;\n}\n\nfunction uploadFile(file, i) {\n    updateProgress(i, 100)\n}\n\nasync function handleFiles(files) {\n    console.log(files)\n    const file = files[0]\n\n    files = [...files]\n    console.log(files)\n    initializeProgress(files.length)\n    files.forEach(uploadFile)\n\n    if (files[0]) {\n        var reader = new FileReader();\n\n        reader.onload = function (e) {\n            videoSrc.src = e.target.result\n            videoTag.load()\n        }.bind(this)\n\n        reader.readAsDataURL(files[0]);\n    }\n\n}\n```\n\n## Step 4. Adding the logic for  Video NFT SDK.js \n\nThe code has a function to mint your video nft to the `polygon testnet` mint\n\nMake sure you are in a `polygon testnet` network to mint \n\n```javascript\nconst apiOpts = {};\n\nasync function mintNft() {\n    const provider = new ethers.providers.Web3Provider(window.ethereum, \"any\");\n\n    // Prompt user for account connections\n    await provider.send(\"eth_requestAccounts\", []);\n    let ethereum = window.ethereum;\n    let chainId = window.ethereum.chainId;\n\n\n    const signer = provider.getSigner();\n    console.log(\"Account:\", await signer.getAddress());\n    console.log(ethereum)\n    console.log(chainId);\n\n    const minter = new videonft.minter.FullMinter(apiOpts, { ethereum, chainId });\n\n    console.log(minter);\n    let file = document.getElementById('file').files[0];\n    let title = document.getElementById(\"title\").value || \"My NFT\";\n    console.log(title)\n    console.log(file)\n    let asset = await minter.api.createAsset(title, file);\n    console.log(asset);\n    // // optional, optimizes the video for the NFT\n    asset = await minter.api.nftNormalize(asset);\n    console.log(asset)\n    const nftMetadata = {\n        description: 'My NFT description',\n        traits: { 'my-custom-trait': 'my-custom-value' }\n    };\n    console.log(nftMetadata)\n\n    const nftInfo = await minter.createNft({\n        name: title,\n        file,\n        nftMetadata\n    });\n    console.log(`minted NFT on contract ${nftInfo.contractAddress} with ID ${nftInfo.tokenId}`);\n    return nftInfo;\n}\n```\n\nOptional:  \nif you want to deploy on vercel you will need the vercel.json file\n\n```json\n{\n    \"version\": 2,\n    \"builds\": [\n        {\n            \"src\": \"./index.js\",\n            \"use\": \"@vercel/node\"\n        }\n    ],\n    \"routes\": [\n        {\n            \"src\": \"/(.*)\",\n            \"dest\": \"/\"\n        }\n    ]\n  }\n```\n\n\n🎂 Congrats! You finished building an video nft uploader! \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flivepeer%2Fvideo-nft-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flivepeer%2Fvideo-nft-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flivepeer%2Fvideo-nft-sample/lists"}