gaspard7/wiki_gpac huggingface dataset:
Advanced splicing

You can use the splicer to mark splicing periods boundaries but not replace the content, using the `mark` directive. In that case, the splice period does not consume any source entry.

A good use case is remote ad insertion in DASH, where the main content is always described in the manifest but ad periods also provide an XLINK to replacement content:

  
```
##begin pl.m3u
#out=4 in=10 mark sprops=#xlink=http://foo.bar/ad.mpd
main:#Period=Main
##end playlist

gpac -i pl.m3u -o dash/live.mpd
```

This will generate 3 DASH periods, the second period having an `xlink:href="http://foo.bar/ad.mpd"` set, but still describing the main content. 

The `sprops` directive gives a set of PID properties to apply to the output PIDs from the `main` content during the splicing period only. These PID properties are restored to their original state (i.e. input PID props + `props` directive if any) at the end of the splice period.


You can also use the splicer to add content to the main content during the splicing period, rather than replacing it, using the `keep` directive. The `sprops` directive can also be used in this mode.

For example, if one period of your DASH session offers more streams than the others:


```
##begin pl.m3u
#out=4 in=10 keep props=#Period=Main
main:#Language=us-US
ad:#Language=fr-FR:#Period=Ins
##end playlist

gpac -i pl.m3u -o dash/live.mpd
```

This will generate 3 DASH periods, the second period (`Ins`) having an additional content (one or more adaptation sets) with language `fr-FR`.
Dynamic playlists

When doing splicing, the playlist is always dynamic and can be reloaded at any time. Once a splicing period is over for the main content, a new splicing period can be configured by modifying the playlist, overwriting the `in` and `out` values. 
 

```
##begin pl.m3u
#out= in=
main
ad
##end playlist

gpac -i pl.m3u -o dash/live.mpd
```

This will play `main`, waiting for the playlist to be modified.

Then edit the playlist as follows:
```
##update pl.m3u
#out=now in=+10
main
ad
##end playlist
```

This will resolve the splice start time to be the next SAP found on video stream, and the splice end time to be 10s after the splice start. You can use for `out` and `in`:

- a time in seconds. This time is expressed in the `main` media timeline
- a date in XSD dateTime format
- `now`, as explained previously
- an empty value to indicate the media is to be spliced but the start or end time of the splice is still unknown

You can also use for `in` a delta from the `out` value, expressed in seconds (as in the previous example).

_Note: The value `now` is equivalent to the empty value (i.e. undefined) for the first playlist load._


Once the end of the splice is reached, the next URL to load for a splice is reset to the next URL after the main content.

To load a new ad, simply update the playlist before the next target splice start:

```
##update pl.m3u
#out=now in=+15
main
ad2
##end playlist
```
Timeline re-alignment during concatenation / splicing

When concatenating media streams (whether at the end of a previous media or at a splice point), the encoding characteristics of the source usually result in audio and video streams of different duration at the insertion point.

When concatenating, the filter will use the highest frame time on all streams, and realign the next timeline starting from that point. For example:

- video @25fps, duration 10.0s
- AAC 44100Hz, duration 10.03102s

The next source timeline origin will be the last audio time (10.03102s), which will result in:

- the next audio frame starting exactly after the last audio
- the next video frame starting at 31.02 ms after the last video frame, introducing a gap in video

The same logic applies when the audio is shorter than the video, in that case introducing a gap in the audio.

This logic is always applied by default, regardless of the new source to concatenate. This means that even if the next source has the proper time offset between audio and video streams, its timeline is still reset and a gap is introduced.
You can prevent this by assigning the directive `nosync` to the new source:

```
##start playlist
src1.mp4
#nosync
src2.mp4
##end playlist
```

In this example, the resulting timeline will have no gap, but may have synchronization slightly off for media of `src2`.

The timeline of the first media loaded in the playlist (whether splicing or not) is not realigned. 


When splicing, the same logic applies and the `nosync` directive can also be used for media to be inserted in the splice period.

Note however that the `nosync` cannot be specified for main content resume, so there could still be gaps in the timeline if encoding characteristics differ (different codecs, different frame rates or sample rates).
Media Streams inspection {: data-level="beginner" }

```
gpac -i source.mp4 inspect
```

The above command will open the given `source.mp4` file and print information for each PID found in the source to stdout. Once all PIDs are found (that is, once a packet is delivered on each PID), inspection will stop.

```
gpac -i source.mp4 inspect:full
```

This is the same as previous command but with complete PID properties report.

```gpac -i source.ts inspect:log=stderr:allp```

The above command will open the given `source.ts` file and print properties of each PID found in the source to stderr. It will analyse the entire file, so that if a PID configuration change happens in the source, it will be reported.


__Discussion__  
As usual with ```gpac```, any source can be used, and any number of sources can also be used with the inspect filter.

```
gpac -i source1.h264 -i source2.aac inspect
```

And any filter chain can be inspected. For example, the following inspects the decoded output of a source: 
```
gpac -i source1.h264 reframer:raw inspect
```
Packet inspection

```
gpac -i source.mp4 inspect:deep
```

The above command will open the given `source.mp4` file and print properties of each PID found in the source and properties of each packet of each PID. There is no guarantee of the order of packets, depending on source type, scheduling modes, etc.   

To force separate reporting per PID, use

```
gpac -i source.mp4 inspect:deep:interleave=false
```


The start and duration of the inspection can be modified:

```
gpac -i source.mp4 inspect:deep:start=10:dur=1
```

This will force inspecting from start time 10 second (or previous access point) for 1 second.
Filtering the inspection

There are many cases where all the information of each packet is not really useful to understand a file. You can filter the packet properties you want to dump using the [fmt](inspect#fmt) option. 
```
gpac -i source.mp4 inspect:interleave=false:fmt=%num%-%dts%-%cts%-%sap%-%size%%lf%:log=dump.txt
```

The above command will open the given `source.mp4` file and print properties of each PID found in the source and for each packet, will report its number, dts, cts, RAP/SAP type and size, one packet per line:
```
1-0-0-1-200
2-1-1-0-10
...
```

The full list of options for the packet information log is given in the [inspect](inspect) filter help.

```
gpac -i source.mp4 inspect:interleave=false:fmt="PCK%num% DTS=%dts% CTS=%cts% SAP=%sap% size=%size%%lf%":log=dump.txt
```

This is the same as above with some nicer formatting of the output:
```
PCK1 DTS=0 CTS=0 SAP=1 size=200
PCK2 DTS=1 CTS=1 SAP=0 size=10
...
```
Analysing a source

It is possible to use the filter to produce a detailed trace of the media frames, in XML:
```
gpac -i source.mp4 inspect:interleave=false:analyze=on
gpac -i source.mp4 inspect:interleave=false:deep:analyze=on
```

The above command will open the given `source.mp4` file and create an XML dump of all PID media-specific info and all packets media-specific info if [deep](inspect#deep) is set. 

The analyze mode will check the payload of the decoder configuration (parameter sets)  and the payload of each packet. Supported bitstream formats for analysis are:

- AVC, HEVC, VVC video
- AV1
- VP8,VP9
- MPEG1/2/4 video
- ProRes video
- MPEG1/2 audio
- AC3 / EAC3 audio
- MPEG4 AAC and USAC audio: configuration only
- Timecodes tracks and some subtitles (XML, text)


Using the mode `analyse=bs` will give, for supported media types, the fields read from the bitstream, and  `analyse=full` will also give the number of bits for each field.

This is still a work in progress, more media types need to be added and deeper analysis of the packets should be done (for now only the slice headers are parsed).

This should however help you check consistency of systems layer information (timing, SAP, dependency information) with frame properties.
Overview {: data-level="all" }

We discuss here how to use encoders in GPAC.  

GPAC filter graph resolution always targets the shortest possible path between two filters to link them. This implies that for a given source, encoders may or may not be triggered depending on the destination.  
For example, if the source is an AAC file and the destination is an ISOBMFF file, since ISOBMFF accepts AAC data inputs, no encoder will be used. But if the source is an AAC file and the destination is an MP3 file, the graph resolver will load a decoder and an MP3 encoder to move source data from AAC to MP3.
Encoding from a raw video file

```gpac -i source.yuv:size=1280x720 -o test.avc```

The above command will encode the `source.yuv`  YUV420 8-bits into AVC|H264 using default encoding parameters of the encoder used. This may load a filter chain to adapt the PCM data to another format (floating point, etc ...).

```gpac -i source.yuv:size=1280x720 enc:c=avc -o test.mp4```

The above command will encode the `source.yuv`  YUV420 8-bits into AVC|H264 using default encoding parameters of the encoder used and mux this into MP4. 


__Discussion__  
Prior to GPAC 2.0, the following command had to be used:
```gpac -i source.yuv:size=1280x720 enc:c=avc @ -o test.mp4```
The link directive `@` is used here to prevent the raw YUV/RGB data PID to link against the `test.mp4` destination which would accept it. When a PID can directly connect to a filter without any adaptation chain, the graph resolver will not try to connect it to any other filters unless sourceIDs are explicitly set, as described in the [general documentation](filters_general#filter-linking-link). GPAC 2.0  and above simplified command line processing to avoid link directives in most cases.

The `enc` filter is an [internal reserved filter class](filters_general#specifying-encoders-and-decoders) used by GPAC to load an encoder satisfying the format given by `c=`. This means that if several encoders provide this format, the first one with the highest priority will be used.

You can directly call your preferred encoder rather than letting the link resolver pick it for you:

```gpac -i source.yuv:size=1280x720 ffenc:c=avc -o test.mp4```

This will explicitly load the FFmpeg encoder to do the job.

Note that for `ffenc`, since the filter provides all encoders supported by your FFmpeg build, you may have several choices within FFmpeg itself. To specify the true desired codec rather than the format, use the codec name directly:

```
gpac -i source.yuv:size=1280x720 enc:c=libx264 -o test.mp4
gpac -i source.yuv:size=1280x720 enc:c=libx264rgb -o test.mp4
```
__Warning: Hardware encoders of FFmpeg have not been tested yet!__
Transcoding from a non raw video file

```gpac -i source.mp4 c=avc -o test.avc```

The above command will encode the video track in  `source.mp4`  into AVC|H264 using default encoding parameters of the encoder used and dump this as Annex B format (start codes).  

__Discussion__  
Prior to GPAC 2.0, the following command had to be used:
```gpac -i source.mp4 enc:c=avc @ -o test.avc```
As explained previously, the link directive `@` ensures that we do the transcoding. If we omit this directive and the `source.mp4` file has an AVC|H264 track in it, this track will simply be dumped to `test.avc`with no transcoding used. However, if we omit this and the file has video track __NOT__ in AVC|H264 format, the video will be transcoded.
Setting encoder parameters

Currently, all encoders audio and video in GPAC are using FFmpeg. We therefore only illustrate encoder parameters with the [ffenc](ffenc) filter.

```gpac -i source.mp4 c=avc:b=2M -o test.avc```

The above command will encode the video track in  `source.mp4`  into AVC|H264 at 2 mbits per seconds.

```gpac -i source.mp4 c=avc:fintra=2:b=500k -o test.avc```

The above command will encode the video track in  `source.mp4`  into AVC|H264 at 500 kbps and enforce intra frames using [fintra](ffenc) every 2 seconds. This doesn't prevent the encoder to produce intra frames within this period (e.g. scene cut), but ensures you always have IDRs at the right period. This is obviously designed for HTTP Adaptive Streaming.


```gpac -i source.mp4 c=avc::x264-params=no-mbtree:sync-lookahead=0::profile=baseline -o test.avc```

The above command will encode the video track in  `source.mp4`  into AVC|H264 and pass two options to FFmpeg encoder:

-  `x264-params`, with value `no-mbtree:sync-lookahead=0`
-  `profile`, with value `baseline`

__Discussion__  
Note the usage of double colon in the command line. As explained [here](filters_general#specifying-encoders-and-decoders), this prevents the filter resolver to interpret arguments of `x264-params` as arguments of the ffenc filter; this is needed here since both gpac and libx264 use `:`-separated list of `key=value` pairs. Another possibility would be to change the set of separators used by GPAC using [-seps](gpac_general#seps). 

To get a list of all generic options supported by the [ffenc](ffenc) filter, use `gpac -h ffenc`.  

To get a list of all options supported by a given encoder of the ffenc filter, for example libx264, use `gpac -h ffenc:libx264`.

```gpac -i source.mp4 enc:c=avc:pfmt=yuv2 -o test.avc```
The above command will encode the video track in  `source.mp4`  into AVC|H264, converting the source data to YUV 422 8bit planar.

__Discussion__  
FFmpeg usually comes with several variations of the same coding type, with different pixel format supported. For example, AVC|H264 encoding can use both `libx264` and `libx264_rgb` encoders. If the source data is decoded into RGB by the decoder, the `ffenc` filter will match the `libx264_rgb` encoder as supporting RGB input and AVC format. The resulting file may be in a profile not supported by most devices !  

Setting the pixel format using [pfmt](ffenc) will make sure you encode in YUV format; alternatively, you can also enforce the encoder used by setting `ffc=libx264`. 

_Note: The `pfmt` option is a generic option of all present and future encoders in GPAC, while `ffc` option is specific to FFmpeg encoder._
Changing Resolution

You can use the [ffsws](ffsws) filter to rescale videos in your pipeline:
 

```gpac -i source.mp4 ffsws:osize=1280x720 c=avc:b=1m -o test.avc```

This will resize (downscale or upscale) input to a resolution of 1280x720 without checking aspect ratio, and encode to AVC at 1 mbps. To keep aspect ratio, use `ffsws:osize=1280x720:keepar=full`.
Encoding from files

This is basically the same as video

```gpac -i source.pcm:sr=48k:ch=2 -o test.aac```

The above command will encode the `source.pcm` 48000 Hz stereo signed 16 bit PCM into AAC using default encoding parameters of the encoder used. This may load a filter chain to adapt the PCM data to another format (floating point, etc ...).
 
```gpac -i source.mp4 enc:c=aac -o test.mp4```

The above command will encode the `source.mp4` audio tracks into AAC, even if the track is already in AAC format, and use FFmpeg `aac` encoder for the job. Note that the `ffc` option will only be used by the ffenc filter. If another filter provides AAC encoding and is used to encode the stream, the `ffc` option will likely be reported as not used by the filter session.
Transcoding AV file {: data-level="beginner" }

Combine the above tow steps:

```gpac -i av_source c=avc:b=2m c=aac:b=128k -o test.mp4```


If you only want video transcode, omit the audio encoder:

```gpac -i av_source c=avc:b=2m -o test.mp4```

If you only want audio transcode, omit the video encoder:

```gpac -i av_source c=aac:b=128k -o test.mp4```
Overview {: data-level="all" }

We discuss here how to use [GPAC Filters](Filters) in NodeJS. 

This GPAC node-API provides bindings to GPAC filter session. The design is almost identical to the [Python](python) bindings, closely inspired from the [JS FilterSession](jssession) API used in GPAC.

The GPAC Node API is [documented here](https://doxygen.gpac.io/group__nodejs__grp.html).

You can also have a look at the  [test script](https://github.com/gpac/gpac/tree/master/share/nodejs/) in the GPAC repository.


__Warning GPAC NodeJS bindings are only available starting from GPAC 2.0.__
Before you begin {: data-level="beginner" }

The GPAC NodeJS bindings are using [n-api](https://nodejs.org/api/n-api.html) for interfacing with libgpac filter session, while providing an object-oriented wrapper hiding all GPAC C design.

The binding is called gpac_napi.c, and is hosted in GPAC [source tree](https://github.com/gpac/gpac/blob/master/share/nodejs/). It is NOT installed during default install step.

You will need to build the module using `node-gyp`, potentially editing `share/nodejs/binding.gyp` as required for your system.
The `binding.gyp` provided is for GPAC:

- built in regular shared library mode for libgpac (i.e. NodeJS module is not compatible with mp4box-only build)
- installed on your system (gpac headers available in a standard include directory, libgpac in standard lib directory), typically done with `sudo make install` after building gpac


You can then build using:
```
% cd gpac/share/nodejs
% node-gyp configure
% node-gyp build
```

If you don't want to install on your system, you will need to modify the `binding.gyp` file to set the include dir to the root of gpac source tree:

```
"include_dirs": ["<(module_root_dir)/../../include"]
```

- If built using configure and make, you will likely have a custom config.h file, and the build tree root must also be indicated together with the `GPAC_HAVE_CONFIG_H` macro.

- If you build gpac at the top of the gpac source tree (using e.g. `./configure && make`),  the build tree root for node will be `<(module_root_dir)/../..`.

- If you build gpac in gpac/bin/mytest, (using e.g. `mkdir bin/mytest && cd bin/mytest && ../../configure && make`),  the build tree root for node will be `<(module_root_dir)/../../bin/mytest`.

You will also likely need to update the `libraries` property to add the path to your libgpac shared library (typically in bin/gcc of the build tree root).

```
{
    "targets": [{
        "target_name": "gpac",
        "sources": [ "./src/gpac_napi.c"],
        "include_dirs": ["<(module_root_dir)/../../include", "<(module_root_dir)/../.."],
        "libraries": [ '-lgpac',"-L<(module_root_dir)/../../bin/gcc"],
        "defines":["GPAC_HAVE_CONFIG_H"]
    }]
}

```

The build is usually located in `$GPAC_SRC/share/node/build/Release` so you will need to specify the full path to the module in your JS file:

```
const gpac = require('./build/Release/gpac');
```

or if you want to use the provided `index.js`, simply use:
```
const gpac = require(path/to/gpac/share/nodejs);
```

Check everything is in place running the following JS:


```
const gpac = require('./build/Release/gpac');

console.log("Welcome to GPAC NodeJS !\nVersion: " + gpac.version);
```

Running this should print your current GPAC version. 

A test program [gpac.js](https://github.com/gpac/gpac/blob/master/share/nodejs/test/gpac.js) exercising most of the NodeJS GPAC bindings is available in  `gpac/share/nodejs/test`
Tuning up GPAC {: data-level="beginner" }

The first thing to do is to initialize libgpac. This is done by default while importing the bindings with the following settings:

- no memory tracking
- default GPAC profile used

If you want to change these, you need to re-init libgpac right after import:

```
gpac.init(1, "customprofile");
```

Any call other than `init`  to GPAC will prevent any subsequent call to `init` to be executed.

Before starting any filter session, you may also need to pass some global configuration options (libgpac core or filter options) to GPAC:

```
//For example, blacklist some filters, run quiet and set vsync option (for vout)
gpac.set_args(["gpacnode", "-blacklist=filters_you_do_not_want", "-quiet", "--vsync=0"]);
```

You can also pass the command line arguments so that you can specify GPAC options at prompt:
```
gpac.set_args(process.argv);
```

__WARNING: the arguments must all be set together, only the first call to set_args() will be taken into account__
 
You may want to adjust the log tools and levels of GPAC:
```
gpac.set_logs("dash@info");
```
Simple sessions

To create a filter session, the simplest way is to use all defaults value, creating a single-threaded blocking session:

```
fs = new gpac.FilterSession();
```

You can then add your filters as usual. 

Playback example:

```
f1 = fs.load_src("file.mp4");
f2 = fs.load("vout");
fs.run();
```

Remux example:

```
f1 = fs.load_src("file.mp4");
f2 = fs.load_dst("test.ts");
fs.run();
```

Since the session is blocking, you won't be able to run any other JS code until the end of the session.
Non-blocking sessions

A non-blocking session will need to be called on regular basis to process pending filter tasks. It is useful if you need to do other tasks while the session is running and do not want to use callbacks from GPAC for that.

```
fs = gpac.FilterSession(gpac.GF_FS_FLAG_NON_BLOCKING);
f1 = fs.load_src("file.mp4");
f2 = fs.load("vout");
while (1) {
	//do things

	//call session
	fs.run();

	//if last task, GPAC session is done
	if (fs.last_task) break;
}
```

This allows you to do _some_ JS work on the side, however any JS call involving promises will not work here, as promises are resolved inside NodeJS main event loop and we don't go there until the end of the session.
Async non-blocking sessions

To run the session in non-blocking mode while still allowing NodeJS to run its main event loop and resolve other promises, you will need to run the session as a promise. The following example is creating a promise recursively calling itself until the end of the session:

```
//create session in non-blocking mode:
let fs = new gpac.FilterSession(gpac.GF_FS_FLAG_NON_BLOCKING);

//setup your filters

//Run session as Promise
const FilterSessionPromise = (fs_run_task) => {
  var fsrun_promise = () => {
    return (fs.last_task==false) ? fs_run_task().then(fsrun_promise) : Promise.resolve();
  }
  return fsrun_promise();
};

const run_task = () => {
	return new Promise((resolve, reject) => {
	  resolve( fs.run_step() );
	});
}
FilterSessionPromise(run_task).then( ).finally( ()=> { console.log('session is done'); } ) );

console.log('Entering NodeJS EventLoop');
```
Callbacks in sessions

Regardless of the way you run the session, you can request for being called back once or on regular basis. This is achieved by posting tasks to the GPAC session scheduler. A task object shall provide an `execute` method to be called. This function may return:

-  `false` to cancel the task, 
- `true` to reschedule the task asap
- a positive integer giving the time of next task callback in milliseconds

The callback function is called with `this` set to the task object.

```
//create a custom task
task = {};
task.execute = () => {
	console.log('in task'); 
	return 1000;
};
fs.post(task);

//run as usual
```
  
Tasks can be created at any time, either at the beginning or in a callback function (e.g., another task).

_NOTE When running the session in multi-thread mode, callback tasks are always executed by the main thread (NodeJS main)._
Linking filters

In order to link filters when desired, you must explicitly do this using `set_source` of the destination filter. For example, when inserting a [reframer](reframer) in a chain:

```
f_src = fs.load_src('source.mp4');
f_dst = fs.load_dst('remux.mp4');
f_reframe = fs.load('reframer');
f_dst.set_source(reframer);
```

You can specify the usual link filtering as an optional argument to `set_source`:
```
f_dst.set_source(reframer, "#PID=1");
```

This will instruct that the destination only accepts PIDs coming from the reframer filter, and with ID 1.