# woobi

> stream media across a lan

Latest version **1.1.3** (published 2017-10-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install woobi
pnpm add woobi
yarn add woobi
bun add woobi
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.3 |
| Published | 2017-10-29 |
| First published | 2016-11-14 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 41 |
| Known vulnerabilities | 0 (+11 in 1 direct dependencies) |
| Install scripts | yes |
| GitHub stars | 3 |
| Author | woobi |
| Maintainers | woobi |
| Keywords | ffmpeg, stream, iptv, ui, video, audio, mp4, hls, x11grab, webcam, http, rtsp, udp, mp3, media |

## Links

- npm: https://www.npmjs.com/package/woobi
- Repository: https://github.com/woobi/woobi
- Homepage: https://github.com/woobi/woobi#readme
- Issues: https://github.com/woobi/woobi/issues
- npm.io page: https://npm.io/package/woobi

## Dependencies (41)

- [hat](https://npm.io/package/hat.md)
- [jspm](https://npm.io/package/jspm.md)
- [async](https://npm.io/package/async.md) 1.5.2
- [debug](https://npm.io/package/debug.md)
- [react](https://npm.io/package/react.md)
- [dotenv](https://npm.io/package/dotenv.md)
- [lodash](https://npm.io/package/lodash.md)
- [moment](https://npm.io/package/moment.md)
- [morgan](https://npm.io/package/morgan.md)
- [multer](https://npm.io/package/multer.md) ^1.2.0
- [express](https://npm.io/package/express.md)
- [respawn](https://npm.io/package/respawn.md) ^2.4.1
- [fs-extra](https://npm.io/package/fs-extra.md) ^0.30.0
- [throttle](https://npm.io/package/throttle.md) ^1.0.3
- [file-size](https://npm.io/package/file-size.md) ^1.0.0
- [nodeadmin](https://npm.io/package/nodeadmin.md) ^0.1.2
- [ratelimit](https://npm.io/package/ratelimit.md) ^0.0.4
- [react-dom](https://npm.io/package/react-dom.md)
- [socket.io](https://npm.io/package/socket.io.md)
- [superagent](https://npm.io/package/superagent.md)
- [body-parser](https://npm.io/package/body-parser.md)
- [compression](https://npm.io/package/compression.md) ^1.6.2
- [find-remove](https://npm.io/package/find-remove.md) ^1.0.0
- [range_check](https://npm.io/package/range_check.md) ^1.4.0
- [errorhandler](https://npm.io/package/errorhandler.md) ^1.4.3
- [express-less](https://npm.io/package/express-less.md)
- [growing-file](https://npm.io/package/growing-file.md) ^0.1.3
- [react-router](https://npm.io/package/react-router.md)
- [ringbufferjs](https://npm.io/package/ringbufferjs.md) ^0.0.1
- [connect-mongo](https://npm.io/package/connect-mongo.md) ^1.3.2
- [fluent-ffmpeg](https://npm.io/package/fluent-ffmpeg.md) ^2.1.0
- [promise-mysql](https://npm.io/package/promise-mysql.md) ^1.3.2
- [express-session](https://npm.io/package/express-session.md)
- [json-safe-parse](https://npm.io/package/json-safe-parse.md) ^0.0.2
- [method-override](https://npm.io/package/method-override.md)
- [model-transform](https://npm.io/package/model-transform.md)
- [chunking-streams](https://npm.io/package/chunking-streams.md) ^0.0.8
- [fixed-data-table](https://npm.io/package/fixed-data-table.md) ^0.6.4
- [sanitize-filename](https://npm.io/package/sanitize-filename.md) ^1.6.1
- [react-style-proptype](https://npm.io/package/react-style-proptype.md) ^3.0.0
- [javascript-natural-sort](https://npm.io/package/javascript-natural-sort.md) ^0.7.1

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 1.1.3 (latest) — 2017-10-29
- 1.0.1 (beta) — 2016-11-14
- 1.1.2 — 2017-10-29
- 1.1.0 — 2017-10-29
- 1.0.10 — 2016-11-20
- 1.0.9 — 2016-11-20
- 1.0.8 — 2016-11-20
- 1.0.7 — 2016-11-15
- 1.0.5 — 2016-11-14
- 1.0.4 — 2016-11-14
- 1.0.3 — 2016-11-14
- 1.0.2 — 2016-11-14

## README

Woobi Media Streams
==================
EPG ui, LAN media server, IPTV broadcaster, and media converter.  
- Stream the same media to multiple locations at once using multicast or unicast/http.
- Stream your desktop to gaming/live servers.
- Use a tv tuner to stream tv to all connected devices.  
- EPG with DVR controls via adapter.  


## Contents
[Pre-Requisites](#pre-requisites)  
[Installation](#installation)   
[Usage](#usage)  
[Woobi UI](#woobi-ui)  
[Configuration](#configuration)   

[Woobi.Channel](#woobichannel)
  - [Options](#options)
  - [Adding Assets](#adding-assets)
  - [Properties](#properties)  
  - [API Routes](#api-routes)
  - [Watch / Listen](#watch--listen)

[Woobi.Sources](#woobisources)
  - [.File](#fileoptions-callback)  
  - [.Fluent](#fluentoptions-callback)  
  - [.Program](#programoptions-callback)  
  - [.UDP](#udpoptions-callback)  

[Woobi.Streams](#woobistreams)  
  - [.bridge](#bridge)
  - [.HLS](#hlsoptions-callback)
  - [.MpegTS](#mpegtsoptions-callback)
  - [.throttle](#throttlesource-rate-onend)
  - [.transform](#transform)
  - [.UDP](#udpoptions-callback-1)


[Screen Shots](#screen-shots)  
[Contributing](#contributing)  
[License](#license)  


## Pre-Requisites
You need ffmpeg and node >= v4.

## Installation  
```bash
yarn install woobi
``` 


## Usage  
```javascript
var Woobi = require('woobi');
Woobi.init( {
	channelPort: 13000,
	host: 'studio',
	loadSaved: false,
	proxy: {
		port: 2777,
		nodeadmin: false,
		host: '0.0.0.0',
	},
	adapters:  [
		/* the included media adapter is for a mysql database setup */
		{
			name: 'media',
			adapter: 'media',
			config: {
				user: 'MYSQLUSER',
				pass: 'MYSQLPASS',
				host: 'MYSQLHOST',
				database: 'MYSQLDB'
			},
		},
		/* custom adapters can be added. use the included adapters as a template */
		{
			name: 'livetv',
			adapter: function ( Woobi ) {
			
				var MyAdapter = function ( opts, callback ) {
		
					if ( !( this instanceof MyAdapter ) ) return new MyAdapter( opts, callback );
					
				}
				
				/* Add any function available in /lib/core/apapters.js */
				MyAdapter.prototype.getGuideData = function ( channels, start, end ) {
				
				}
				return MyAdapter;
			
			},
			config: {
				
			}
		},
		/* The included live tv adapter uses a mix of mysql databases and direct tcp connections */
		{
			name: 'livetv',
			adapter: 'livetv',
			config: {
				epg: {
					user: 'MYSQLUSER',
					pass: 'MYSQLPASS',
					host: 'MYSQLHOST',
					database: 'MYSQLDB'
				},
				tv: {
					user: 'MYSQLUSER',
					pass: 'MYSQLPASS',
					host: 'MYSQLHOST',
					database: 'MYSQLDB'
				},
				socket: {
					host: 'anna',
					port: '9080',
					hostname: 'studio',
					agent: 'Woobi'
				},
			}
		},
	]
});
```  

## Woobi UI
http://localhost:7001  
If you set the `proxy` option you can use the Woobi UI.
- Live Tv EPG and DVR Manager (ui only)  
- Create Channels  
- View Channels  
- Save / Manage Channels  
- View local library  


## Configuration 
#### Woobi.init(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
> return **Promise**  
>  
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **host** | _String_ | Host to use to access Woobi UI and api routes.  |
| **proxy** | _false\|Object_ | Optional server for api routes and Woobi UI. |
| **adapters** | _Object\|Array_ | Adapters can convert your info to the correct format.  |
| **loadSaved** | _Boolean_ | Load saved channels on boot that are set to autostart.  |
| **channelPort** | _Number_ | If you do not supply a port when streaming a channel, the port will be assigned starting at this number.  | 
| **mediaPath** | _String_ | Full path to store saved HLS files.  Defaults to **/_module_path_/media**  |
| **media passthrough route** | _String_ | Api route to direct access media.  |
| **media passthrough path** | _String_ | Replace the path above with the actual server path.  |
| **video passthrough route** | _String_ | Api route to direct access videos.  |
| **video passthrough path** | _String_ | Replace the path above with the actual server path.  |
>  
##### proxy object  
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **host** | _String_ | Host to start on. default 0.0.0.0  |
| **port** | _Object_ | Port for api routes and Woobi UI access. |
| **keystone** | _Boolean_ | Use keystone if you want to save channel configs from the UI.  |
| **nodeadmin** | _Boolean_ | Load the nodeadmin app.  |
| **auth** | _Boolean_ | Used with keystone. Set to false at first to create a new user @ http://localhost/keystone  |
> You can add any keystone option to the proxy configuration.   
> If you want to use channel saving and do not want to use keystone, then attach a mongoose model to `Woobi.libs._mongo.ChannelConfig.model`
##### adapters Array of Objects  
> Adapters are used to convert your information into the required format for the UI.  
> You can also uses adapters for non-ui use cases.   
> For local media a `media` adapter is needed.  An example using mysql databases is included.  
> For live tv a `livetv` adapter is needed. An example using a mix of mysql databses and tcp connections is supplied.  
  
>  Adapters are available at `Woobi.libs['USER_SUPPLIED_NAME']`  


| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for the adapter.  Can be accessed at `Woobi.libs[name]`  |
| **adapter** | _String\|Function_ | String for included adapter or a function to provide your own. |
| **config** | _Object_ | |
| **config.user** | _String_ | username  |
| **config.pass** | _String_ | password |
| **config.host** | _String_ | host |
| **config.database** | _String_ | database |  

View `/lib/core/adapter.js` for all available functions to use.  
> **note** - A `media` and `livetv` adapters are used by the UI if supplied.  
> **note** - config will be passed to custom adapters and can include additional key/value pairs

>  The media adapter needs the following functions  
>  `tvShow( idShow )` `tvShows( obj )` `tvShowByName( name )` `tvShowByIMDB( imdb_id )`  
>  `tvShowEpisodes( idShow )` `recentEpisodes( obj )`   
>  `movie( idShow )` `movies( obj )` `movieByName( name )`  
>  `movieByIMDB( imdb_id )`  `recentMovies( obj )`
>  `grabMedia( obj )` `mediaFiles( obj )` `mediaFile( obj )`  

>  The livetv adapter needs the following functions  
>  `connect( obj )` `getGuideData( channels, start, end )` `getSeriesTimers( obj )` `getTimers( obj )` `getTVChannels( obj )` `getChannelGroups( obj )` 

## Woobi.Channel  
>  Use **`Woobi.addChannel( name, opts ).then()`** to add channels instead of directly with `new Woobi.Channel( name, opts, callback )`.    

```javascript 
/**
 * This gives iptv by grabbing a 
 * tv tuner card source and sending it over udp
 * For wired networks a multicast can be used
 **/
Woobi.addChannel( 'TV', {
	loop: true,
	assets: [
		{
			type: 'program',
			name: 'Air',
			arg: 'gnutv -channels /home/woobi/dvb/channels.conf -out udp 10.10.10.82 13333 WAGA5',
			redo: 'gnutv -channels /home/woobi/dvb/channels.conf -out udp 10.10.10.82 13333 ##CMD##',
		},
		{
			type: 'udpSink',
			port: 13333,
			host: '10.10.10.82',
			name: 'AirTV',
		},
		{
			type: 'udpStream',
			port: 13333,
			host: '10.10.10.87',
			name: 'streamAir'
		},
		
	],
}, ( err ) => {
	if ( err ) console.log( '##ERROR##', err );
});

/**
 * using the library adapter
 **/
Woobi.libs.media.movies()
.then( ( movies ) => {
    movies = movies.map( r => {
		return { name: r.name, file: r.file, progress: true, metadata: r, encode: false }
    });
    return Woobi.addChannel( 'recentMovies', {
		files: movies,
		loop: true,
		noTransition: true,
		hls: {
			type: 'hls',
			name: 'movieChannel',
			passthrough: true, // uses the stream as is / no transcoding
		}
    });
})
.catch( ( err ) => {
    if ( err ) debug( '##ERROR##', err );
});

// channel is now available at Woobi.channels.recentMovies
```
### Options
### Adding Assets
### Properties
### API Routes
### Watch / Listen  

## Woobi.Sources
#### .File(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let file = new Woobi.Sources.File({
    name: 'Test',
    file: '/home/woobi/Pitures/woobi.mp3'
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **file** | _Object_ | Full path to file. |

#### .Fluent(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let fluent = new Woobi.Sources.Fluent({
    name: 'Test',
    file: '/home/woobi/Videos/woobi.mp4',
    streamable: true
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **file** | _Object_ | *optional* Full path to file. |
| **stream** | _Object_ | *optional* Source stream. |
| **progress** | _Boolean_ | Emit progress info.  |
| **metadata** | _Object_ | Object of information about file. Should be flat with exception of the `art` key(an Array).  | 
| **seek** | _Number_ |  |
| **inputFormat** | _String_ |  |
| **inputOptions** |  _Array\|String_ |  |
| **outputOptions** |  _Array\|String_ |  |
| **videoFilters** | _Object_ |  |
| **onlyOptions** | _Array\|String_ |  |
| **encode** | _Boolean_ |  |
| **streamable** | _Boolean_ |  |
| **format** | _String_ |  |

#### .Program(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let program = new Woobi.Sources.Program({
    name: 'TV',
    program: 'gnutv',
    arg: '-channels /home/woobi/dvb/channels.conf -out udp 10.10.10.82 13333 WAGA5',
    redo: '-channels /home/woobi/dvb/channels.conf -out udp 10.10.10.82 13333 ##CMD##',
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **program** | _String_ | Program name. |
| **args** | _String_ | Argument String. |
| **redo** | _String_ | String used to restart program. |

#### .UDP(options, callback)   
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let updSource = new Woobi.Sources.UDP({
    name: 'UDPSource',
    host: '10.10.10.10',
    port: 7005
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **host** | _String_ |  |
| **port** | _Number_ |  |

## Woobi.Streams
#### .bridge() 
>   
```javascript
let bridge = new Woobi.Streams.bridge();
```
> normal passthrough stream

#### .HLS(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let hls = new Woobi.Streams.HLS({
    name: 'Test',
    file: '/home/woobi/Videos/woobi.mp4',
    streamable: true
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **file** | _Object_ | *optional* Full path to file. |
| **stream** | _Object_ | *optional* Source stream. |
| **progress** | _Boolean_ | Emit progress info.  |
| **metadata** | _Object_ | Object of information about file. Should be flat with exception of the `art` key(an Array).  | 
| **seek** | _Number_ |  |
| **inputFormat** | _String_ |  |
| **inputOptions** |  _Array\|String_ |  |
| **outputOptions** |  _Array\|String_ |  |
| **onlyOptions** | _Array\|String_ |  |
| **hlsOptions** | _Array\|String_ |  |
| **passthrough** | _Boolean_ |  |
| **streamable** | _Boolean_ |  |
| **format** | _String_ |  |

#### .MpegTS(options, callback)  
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let mpegts = new Woobi.Streams.MpegTS({
    name: 'Test',
    file: '/home/woobi/Videos/woobi.mp4',
    streamable: true
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **program** | _String_ |  |
| **path** | _String_ |  |
| **urlPath** | _String_ |  |
| **source** | _Object_ | input source. |
| **video** | _String_ |  |
| **audio** | _String_ |  |
| **other** | _String_ |  |
| **segment** | _String_ |  |

#### .throttle(source, rate, onEnd)
> @param - **source** - Stream  
> @param - **rate** - Number
> @param - **onEnd** - Function
```javascript
let throttle = new Woobi.Streams.throttle(stream, 1000);
// throttle.stream.pipe(somewhere)
```
> 

#### .transform()
>   
```javascript
let transformer = new Woobi.Streams.transform();
```
> transform stream

#### .UDP(options, callback)   
> @param - **options** - Object  
> @param - **callback** - Function  
```javascript
let updStream = new Woobi.Streams.UDP({
    name: 'UDPStream',
    host: '10.10.10.11',
    port: 7006
});
```
| option | type | info |
| :--------------- | :------------ | :------------------ |
| **name** | _String_ | Unique name for asset  |
| **host** | _String_ |  |
| **port** | _Number_ |  |


## Screen Shots

## Contributing

## License

---
_Source: https://npm.io/package/woobi · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
