Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
feat: implementing the new streaming interfaces (#1086)
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias authored Nov 20, 2017
1 parent 1b1fa05 commit 2c4b8b3
Show file tree
Hide file tree
Showing 27 changed files with 476 additions and 566 deletions.
18 changes: 4 additions & 14 deletions examples/browser-browserify/src/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
'use strict'

const concat = require('concat-stream')
const Buffer = require('safe-buffer').Buffer

const IPFS = require('../../../src/core') // replace this by line below
// var IPFS = require('ipfs')

const node = new IPFS({
repo: String(Math.random() + Date.now())
})

node.on('ready', () => {
console.log('IPFS node is ready')
})
node.once('ready', () => console.log('IPFS node is ready'))

function store () {
var toStore = document.getElementById('source').value
Expand All @@ -33,16 +28,11 @@ function store () {

function display (hash) {
// buffer: true results in the returned result being a buffer rather than a stream
node.files.cat(hash, (err, res) => {
if (err || !res) {
return console.error('ipfs cat error', err, res)
}
node.files.cat(hash, (err, data) => {
if (err) { return console.error('ipfs cat error', err) }

document.getElementById('hash').innerText = hash

res.pipe(concat((data) => {
document.getElementById('content').innerText = data
}))
document.getElementById('content').innerText = data
})
}

Expand Down
56 changes: 16 additions & 40 deletions examples/browser-script-tag/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,17 @@
<title>IPFS in the Browser</title>
<script src="https://unpkg.com/ipfs/dist/index.min.js"></script>
<script type="text/javascript">
const repoPath = 'ipfs-' + Math.random()
const node = new Ipfs({ repo: 'ipfs-' + Math.random() })

// Create an IPFS node
const node = new Ipfs({
init: false,
start: false,
repo: repoPath
})

// Init the node
node.init(handleInit)

function handleInit (err) {
if (err) {
throw err
}

node.start(() => {
console.log('Online status: ', node.isOnline() ? 'online' : 'offline')
node.once('ready', () => {
console.log('Online status: ', node.isOnline() ? 'online' : 'offline')

document.getElementById("status").innerHTML= 'Node status: ' + (node.isOnline() ? 'online' : 'offline')
document.getElementById("status").innerHTML= 'Node status: ' + (node.isOnline() ? 'online' : 'offline')

// You can write more code here to use it. Use methods like
// node.files.add, node.files.get. See the API docs here:
// https://github.com/ipfs/interface-ipfs-core/tree/master/API
})
}
// You can write more code here to use it. Use methods like
// node.files.add, node.files.get. See the API docs here:
// https://github.com/ipfs/interface-ipfs-core/tree/master/API
})
</script>
</head>
<body>
Expand All @@ -44,32 +28,24 @@ <h2>Some suggestions</h2>
<p>Try adding a new file:</p>

<code style="display:block; white-space:pre-wrap; background-color:#d7d6d6">
node.files.add(new node.types.Buffer('Hello world!'), (err, res) => {
if (err || !res) {
node.files.add(new node.types.Buffer('Hello world!'), (err, filesAdded) => {
if (err) {
return console.error('Error - ipfs files add', err, res)
}

res.forEach((file) => console.log('successfully stored', file))
filesAdded.forEach((file) => console.log('successfully stored', file.hash))
})
</code>

<p>You can cat that same file. If you used the exact same string as above ('Hello world!') you should have an hash like this: 'QmQzCQn4puG4qu8PVysxZmscmQ5vT1ZXpqo7f58Uh9QfyY'</p>

<code style="display:block; white-space:pre-wrap; background-color:#d7d6d6">
node.files.cat('QmQzCQn4puG4qu8PVysxZmscmQ5vT1ZXpqo7f58Uh9QfyY', function (err, stream) {
var res = ''

stream.on('data', function (chunk) {
res += chunk.toString()
})

stream.on('error', function (err) {
console.error('Error - ipfs files cat ', err)
})
node.files.cat('QmQzCQn4puG4qu8PVysxZmscmQ5vT1ZXpqo7f58Uh9QfyY', function (err, data) {
if (err) {
return console.error('Error - ipfs files cat', err, res)
}

stream.on('end', function () {
console.log('Got:', res)
})
console.log(data.toString())
})
</code>
</body>
Expand Down
3 changes: 3 additions & 0 deletions examples/browser-video-streaming/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This example shows a method for video/audio streaming in the browser over IPFS.

## Why use HLS?

HLS (Apple's HTTP Live Streaming) is one of several protocols currently available for adaptive bitrate streaming.

One of the advantages of HLS over some other streaming technologies is that the content can be hosted on a plain old web server without any special server-side support. The way this works is that the original content (the stream or video/audio file) is split up into small MPEG2-TS segments before being uploaded to the server. The segments are then fetched by the HLS player on the fly (using regular HTTP GET requests) and get spliced together to a continuous stream.
Expand All @@ -12,6 +13,7 @@ In addition to the segments there are also so-called manifests (m3u8 files) whic
The fact that HLS content is just "a bunch of files" makes it a good choice for IPFS (another protocol that works this way is MPEG-DASH, which could certainly be a good choice as well). Furthermore, the [hls.js](https://github.com/video-dev/hls.js) library enables straightforward integration with the HTML5 video element.

## hlsjs-ipfs-loader

The hls.js library ships with an HTTP based content loader only, but it's fortunately possible to configure custom content loaders as well, which is what makes IPFS streaming possible in this case. A loader implementation that fetches content using js-ipfs can be found [here](https://www.npmjs.com/package/hlsjs-ipfs-loader), and is easy to use on a regular HTML page:

```html
Expand All @@ -21,6 +23,7 @@ The hls.js library ships with an HTTP based content loader only, but it's fortun
```

## Generating HLS content

In order for any of the above to be useful, we also need to have a way to actually generate HLS manifests and MPEG2-TS segments from an arbitrary video/audio file. Luckily, most new builds of `ffmpeg` are compiled with this capability.

For example, say we have a directory containing a video file `BigBuckBunny_320x180.mp4`. We can then create a sub directory and generate the HLS data there, and finally add it to IPFS:
Expand Down
36 changes: 12 additions & 24 deletions examples/browser-video-streaming/streaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,18 @@

const testhash = 'QmdpAidwAsBGptFB3b6A9Pyi5coEbgjHrL3K2Qrsutmj9K'
const repoPath = 'ipfs-' + Math.random()
const ipfs = new Ipfs({
init: false,
start: false,
repo: repoPath
})
const node = new Ipfs({ repo: repoPath })

ipfs.init((err) => {
if (err) {
throw err
node.on('ready', () => {
Hls.DefaultConfig.loader = HlsjsIpfsLoader
Hls.DefaultConfig.debug = false
if (Hls.isSupported()) {
const video = document.getElementById('video')
const hls = new Hls()
hls.config.ipfs = node
hls.config.ipfsHash = testhash
hls.loadSource('master.m3u8')
hls.attachMedia(video)
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play())
}

ipfs.start(() => {
Hls.DefaultConfig.loader = HlsjsIpfsLoader
Hls.DefaultConfig.debug = false
if (Hls.isSupported()) {
const video = document.getElementById('video')
const hls = new Hls()
hls.config.ipfs = ipfs
hls.config.ipfsHash = testhash
hls.loadSource('master.m3u8')
hls.attachMedia(video)
hls.on(Hls.Events.MANIFEST_PARSED, () => {
video.play()
})
}
})
})
28 changes: 8 additions & 20 deletions examples/browser-webpack/src/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ class App extends React.Component {
function create () {
// Create the IPFS node instance

node = new IPFS({
repo: String(Math.random() + Date.now())
})
node = new IPFS({ repo: String(Math.random() + Date.now()) })

node.on('ready', () => {
node.once('ready', () => {
console.log('IPFS node is ready')
ops()
})
Expand All @@ -47,25 +45,15 @@ class App extends React.Component {
})
})

node.files.add([Buffer.from(stringToUse)], (err, res) => {
if (err) {
throw err
}
node.files.add([Buffer.from(stringToUse)], (err, filesAdded) => {
if (err) { throw err }

const hash = res[0].hash
const hash = filesAdded[0].hash
self.setState({added_file_hash: hash})

node.files.cat(hash, (err, res) => {
if (err) {
throw err
}
let data = ''
res.on('data', (d) => {
data = data + d
})
res.on('end', () => {
self.setState({added_file_contents: data})
})
node.files.cat(hash, (err, data) => {
if (err) { throw err }
self.setState({added_file_contents: data})
})
})
}
Expand Down
4 changes: 2 additions & 2 deletions examples/exchange-files-in-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.0",
"scripts": {
"bundle": "browserify public/js/app.js > public/js/bundle.js",
"serve": "http-server -c-1 -p 12345 public",
"start": "npm run bundle && npm run serve"
"dev": "npm run bundle && npm run start",
"start": "http-server -c-1 -p 12345 public"
},
"license": "MIT",
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/exchange-files-in-browser/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ <h2>Peers</h2>
</div>

<!-- The IPFS node module -->
<script src="//unpkg.com/ipfs/dist/index.min.js"></script>
<!-- <script src="//unpkg.com/ipfs/dist/index.min.js"></script> -->
<!-- <script src="js/app.js"></script> -->
<script src="js/bundle.js"></script>
</body>
Expand Down
Loading

0 comments on commit 2c4b8b3

Please sign in to comment.