Skip to content
Browse files

more livestreaming tweaks

  • Loading branch information...
1 parent f1abd96 commit 5bc2d0f02a18e621781532e99594af58c557a966 @benvanik committed Nov 27, 2011
Showing with 69 additions and 27 deletions.
  1. +10 −5 README.md
  2. +26 −3 examples/transcode.js
  3. +2 −1 src/hls/playlist.cpp
  4. +1 −1 src/hls/playlist.h
  5. +10 −3 src/task.cpp
  6. +12 −9 src/taskoptions.cpp
  7. +7 −4 src/taskoptions.h
  8. +1 −1 src/utils.h
View
15 README.md
@@ -199,16 +199,21 @@ track events.
* [IETF Spec](http://tools.ietf.org/html/draft-pantos-http-live-streaming-07)
* [Apple Docs](http://developer.apple.com/library/ios/#documentation/networkinginternet/conceptual/streamingmediaguide/Introduction/Introduction.html)
-If you are targetting devices that support HTTP Live Streaming (like iOS), you
+If you are targeting devices that support HTTP Live Streaming (like iOS), you
can have the transcoder build the output in realtime as it processes. This
enables playback while the transcoding is occuring, as well as some other fancy
things such as client-side stream switching (changing audio channels/etc).
- // TODO: API for this... something like:
- // (where target is used as a base filename for all the extra stuff)
- var task = transcoding.createTask(source, target, profile, {
- streaming: {
+ var task = transcoding.createTask(source, null, profile, {
+ liveStreaming: {
+ path: '/some/path/',
+ name: 'base_name',
segmentDuration: 10,
allowCaching: true
}
});
+
+This will result in a playlist file and the MPEGTS segments being placed under
+`/some/path/` with the name `base_name.m3u8`. The playlist file will be
+automatically updated as new segments are generated, and files can be assumed to
+be static once they are available.
View
29 examples/transcode.js
@@ -19,6 +19,14 @@ var opts = require('tav').set({
stream_output: {
note: 'Stream file output to test streaming',
value: false
+ },
+ livestreaming: {
+ note: 'Enable HTTP Live Streaming output',
+ value: false
+ },
+ segmentDuration: {
+ note: 'HTTP Live Streaming segment duration',
+ value: 10
}
});
@@ -86,6 +94,9 @@ if (inputFile == '-') {
}
}
+var transcodeOptions = {
+};
+
var target;
if (opts.args.length >= 2) {
var profile = transcoding.profiles[opts['profile']];
@@ -95,7 +106,20 @@ if (opts.args.length >= 2) {
}
var outputFile = opts.args[1];
- if (outputFile == '-') {
+ if (opts['livestreaming']) {
+ // Must be a path
+ var outputPath = path.dirname(outputFile);
+ if (!path.existsSync(outputPath)) {
+ fs.mkdirSync(outputPath);
+ }
+ target = null;
+ transcodeOptions.liveStreaming = {
+ path: outputPath,
+ name: path.basename(outputFile),
+ segmentDuration: parseInt(opts['segmentDuration']),
+ allowCaching: true
+ };
+ } else if (outputFile == '-') {
// STDOUT
target = process.stdout;
} else if (outputFile == 'null') {
@@ -132,8 +156,7 @@ function processQuery(source) {
};
function processTranscode(source, target) {
- var task = transcoding.createTask(source, target, profile, {
- });
+ var task = transcoding.createTask(source, target, profile, transcodeOptions);
task.on('begin', function(sourceInfo, targetInfo) {
// Transcoding beginning
console.log('transcoding beginning...');
View
3 src/hls/playlist.cpp
@@ -4,7 +4,8 @@ using namespace std;
using namespace transcoding;
using namespace transcoding::hls;
-Playlist::Playlist(string path, string name, double duration, bool allowCache) :
+Playlist::Playlist(string& path, string& name,
+ double duration, bool allowCache) :
path(path), name(name), duration(duration) {
TC_LOG_D("Playlist::Playlist(%s, %s, %d, %s)\n",
path.c_str(), name.c_str(), (int)duration,
View
2 src/hls/playlist.h
@@ -12,7 +12,7 @@ namespace hls {
class Playlist {
public:
- Playlist(std::string path, std::string name, double duration,
+ Playlist(std::string& path, std::string& name, double duration,
bool allowCache);
~Playlist();
View
13 src/task.cpp
@@ -164,11 +164,18 @@ Handle<Value> Task::Start(const Arguments& args) {
assert(!task->context);
- // Setup context
- IOReader* input = IOReader::Create(task->source);
- IOWriter* output = IOWriter::Create(task->target);
Profile* profile = new Profile(task->profile);
TaskOptions* options = new TaskOptions(task->options);
+ if (options->liveStreaming) {
+ // Must force to MPEGTS container
+ TC_LOG_D("Task::Start(): HTTP Live Streaming enabled, forcing to MPEGTS\n");
+ profile->container = "mpegts";
+ }
+
+ IOReader* input = IOReader::Create(task->source);
+ IOWriter* output = IOWriter::Create(task->target);
+
+ // Setup context
TaskContext* context = new TaskContext(input, output, profile, options);
// Prepare thread request
View
21 src/taskoptions.cpp
@@ -2,29 +2,32 @@
using namespace transcoding;
-StreamingOptions::StreamingOptions(Handle<Object> source) {
+LiveStreamingOptions::LiveStreamingOptions(Handle<Object> source) {
HandleScope scope;
+ this->path = V8GetString(source, "path", "/tmp/");
+ this->name = V8GetString(source, "name", "video");
+
this->segmentDuration = V8GetNumber(source, "segmentDuration", 10);
this->allowCaching = V8GetBoolean(source, "allowCaching", true);
}
-StreamingOptions::~StreamingOptions() {
+LiveStreamingOptions::~LiveStreamingOptions() {
}
TaskOptions::TaskOptions(Handle<Object> source) :
- streaming(NULL) {
+ liveStreaming(NULL) {
HandleScope scope;
- Local<Object> streaming =
- Local<Object>::Cast(source->Get(String::New("streaming")));
- if (!streaming.IsEmpty()) {
- this->streaming = new StreamingOptions(streaming);
+ Local<Object> liveStreaming =
+ Local<Object>::Cast(source->Get(String::New("liveStreaming")));
+ if (!liveStreaming.IsEmpty()) {
+ this->liveStreaming = new LiveStreamingOptions(liveStreaming);
}
}
TaskOptions::~TaskOptions() {
- if (this->streaming) {
- delete this->streaming;
+ if (this->liveStreaming) {
+ delete this->liveStreaming;
}
}
View
11 src/taskoptions.h
@@ -11,10 +11,13 @@ using namespace v8;
namespace transcoding {
-class StreamingOptions {
+class LiveStreamingOptions {
public:
- StreamingOptions(Handle<Object> source);
- ~StreamingOptions();
+ LiveStreamingOptions(Handle<Object> source);
+ ~LiveStreamingOptions();
+
+ std::string path;
+ std::string name;
double segmentDuration;
bool allowCaching;
@@ -25,7 +28,7 @@ class TaskOptions {
TaskOptions(Handle<Object> source);
~TaskOptions();
- StreamingOptions* streaming;
+ LiveStreamingOptions* liveStreaming;
};
}; // transcoding
View
2 src/utils.h
@@ -58,7 +58,7 @@ do { \
} while(0)
static std::string V8GetString(v8::Handle<v8::Object> obj, const char* name,
- std::string& original) {
+ std::string original) {
v8::HandleScope scope;
v8::Local<v8::String> value =
v8::Local<v8::String>::Cast(obj->Get(v8::String::NewSymbol(name)));

0 comments on commit 5bc2d0f

Please sign in to comment.
Something went wrong with that request. Please try again.