Coder Social home page Coder Social logo

mp4-stream's Introduction

mp4-stream

Streaming mp4 encoder and decoder

npm install mp4-stream

build status

Usage

var mp4 = require('mp4-stream')
var fs = require('fs')

var decode = mp4.decode()

fs.createReadStream('video.mp4')
  .pipe(decode)
  .on('box', function (headers) {
    console.log('found box (' + headers.type + ') (' + headers.length + ')')
    if (headers.type === 'mdat') {
      // you can get the contents as a stream
      console.log('box has stream data (consume stream to continue)')
      decode.stream().resume()
    } else if (headers.type === 'moof') {
      // you can ignore some boxes
      decode.ignore()
    } else {
      // or you can fully decode them
      decode.decode(function (box) {
        console.log('box contents:', box)
      })
    }
  }
  })

All boxes have a type thats a 4 char string with a type name.

API

var stream = mp4.decode()

Create a new decoder.

The decoder is a writable stream you should write a mp4 file to. It emits the following additional events:

  • on('box', headers) - emitted when a new box is found.

Each time the box event fires, you must call one of these three functions:

  • stream.ignore() - ignore the entire box and continue parsing after its end
  • stream.stream() - get a readable stream of the box contents
  • stream.decode(callback) - decode the box, including all childeren in the case of containers, and pass the resulting box object to the callback
var fs = require('fs')
var stream = mp4.decode()

stream.on('box', function (headers) {
  console.log('found new box:', headers)
})

fs.createReadStream('my-video.mp4').pipe(stream)

var stream = mp4.encode()

Create a new encoder.

The encoder is a readable stream you can use to generate a mp4 file. It has the following API:

  • stream.box(box, [callback]) - adds a new mp4 box to the stream.
  • var ws = stream.mediaData(size) - helper that adds an mdat box. write the media content to this stream.
  • stream.finalize() - finalizes the mp4 stream. call this when you're done.
var fs = require('fs')
var stream = mp4.encode()

stream.pipe(fs.createWriteStream('my-new-video.mp4'))

stream.box(anMP4Box, function (err) {
  // box flushed

  var content = stream.mediaData(lengthOfStream, function () {
    // wrote media data
    stream.finalize()
  })

  someContent.pipe(content)
})

Decode and encode a file

To decode and encode an mp4 file with this module do

var encoder = mp4.encode()
var decoder = mp4.decode()

decoder.on('box', function (headers) {
  decoder.decode(function (box) {
    encoder.box(box, next)
  })
})

fs.createReadStream('my-movie.mp4').pipe(decoder)
encoder.pipe(fs.createWriteStream('my-movie-copy.mp4'))

Boxes

Mp4 supports a wide range of boxes, implemented in mp4-box-encoding.

License

MIT

mp4-stream's People

Contributors

feross avatar jasnell avatar jhiesey avatar kkiernan avatar mafintosh avatar nklhtv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mp4-stream's Issues

Stop listing after `stream` atoms

1MiB MP4 Sample: http://www.sample-videos.com/video/mp4/240/big_buck_bunny_240p_1mb.mp4

MP4 structure:

ftyp (32 bytes)
free (8 bytes)
mdat (1046699 bytes)
moov (6904 bytes)

Code snippet:

var mp4 = require('mp4-stream')
var fs = require('fs')

var decode = mp4.decode()

fs.createReadStream('video.mp4')
  .pipe(decode)
  .on('box', function (box, next) {
    console.log('found box (' + box.type + ') at ' + box.offset + ' (' + box.length + ')')
    if (box.container) {
      console.log('box has child boxes (will be emitted next)')
    }
    if (box.stream) {
      console.log('box has stream data (consume stream to continue)')
      box.stream.resume()
    }
    next() // call this when you're done
  })

Result:

found box (ftyp) at 0 (32)
found box (free) at 32 (8)
box has stream data (consume stream to continue)

Stop listing after free atom.

stream.decode(cb) throws Error: Data too short

When calling stream.decode() on the moov box, the mp4-box-encoding module throws an error:

node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:139
    throw new Error('Data too short')
    ^

Error: Data too short
    at Object.Box.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:139:11)
    at exports.AudioSampleEntry.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/boxes.js:374:21)
    at Object.Box.decodeWithoutHeaders (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:169:11)
    at Object.Box.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:142:14)
    at exports.stsd.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/boxes.js:241:21)
    at Object.Box.decodeWithoutHeaders (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:169:11)
    at Object.Box.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:142:14)
    at Object.Box.decodeWithoutHeaders (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:155:23)
    at Object.Box.decode (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:142:14)
    at Object.Box.decodeWithoutHeaders (node_modules/mp4-stream/node_modules/mp4-box-encoding/index.js:155:23)

This is the code:

var fs = require('fs')
var mp4 = require('mp4-stream')

var stream = mp4.decode()

stream.on('box', function (headers) {
  if (headers.type === 'moov') stream.decode(function () {})
  else stream.ignore()
})

fs.createReadStream('./test.m4v').pipe(stream)

Fix example

The next reference is missing in the sample:

var encoder = mp4.encode()
var decoder = mp4.decode()

decoder.on('box', function (headers, next) {
  decoder.decode(function (box) {
    encoder.box(box, next)
  })
})

fs.createReadStream('my-movie.mp4').pipe(decoder)
encoder.pipe(fs.createWriteStream('my-movie-copy.mp4'))

The Sample Size Atoms (stsz) are incorrectly parsed

The sample size atom structure differs slightly from the others, as it has an extra 4 bytes after the version and flags to store the sample size in case its the same for all the samples.

If not, the the sample size entry is set to 0 and the sample size table is used instead. Said table contains an an entry for each sample in the media's data stream.

Source

Because of this error, the parser returns as if the sample size table has no entries.

stream.stream() does not advance the stream

According to the docs, calling stream.stream() should advance the stream so that the box event fires again if there are more boxes. This does not happen.

Below is the code I would expect to work, but it only ever emits the first box. I've validated that the stream returned from stream.stream() does emit an end event, so that's not the issue. Also, it does call the _kick function, but the problem is that _pending isn't 0. I just can't figure out why - could be an off-by-one error.

var fs = require('fs')
var mp4 = require('mp4-stream')

var stream = mp4.decode()

stream.on('box', function (headers) {
  console.log(headers.type)
  stream.stream().resume()
})

fs.createReadStream('./test.m4v').pipe(stream)

server only?

Does this code to run on server side ( such as node.js baed servers ) only? Or would the provided js samples from within a chrome browser?

Working with H.264 frames

I've got a stream pipeline right now which ends in me depaying h.264 frames from RTP packets, could I pipe this into mp4-stream to get a mp4 stream which I could then stream into MSE and show in a video element?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.