0.0.6 -> Master (#731)

* Implement webhook events for external integrations (#574)

* Implement webhook events for external integrations

Reference #556

* move message type to models and remove duplicate

* add json header so content type can be determined

* Pass at migrating webhooks to datastore + management apis (#589)

* Pass at migrating webhooks to datastore + management apis

* Support nil lastUsed timestamps and return back the new webhook on create

* Cleanup from review feedback

* Simplify a bit

Co-authored-by: Aaron Ogle <aaron@geekgonecrazy.com>

Co-authored-by: Gabe Kangas <gabek@real-ity.com>

* Webhook query cleanup

* Access tokens + Send system message external API (#585)

* New add, get and delete access token APIs

* Create auth token middleware

* Update last_used timestamp when using an access token

* Add auth'ed endpoint for sending system messages

* Cleanup

* Update api spec for new apis

* Commit updated API documentation

* Add auth'ed endpoint for sending user chat messages

* Return access token string

* Commit updated API documentation

* Fix route

* Support nil lastUsed time

* Commit updated Javascript packages

* Remove duplicate function post rebase

* Fix msg id generation

* Update controllers/admin/chat.go

Co-authored-by: Aaron Ogle <geekgonecrazy@users.noreply.github.com>

* Webhook query cleanup

* Add SystemMessageSent to EventType

Co-authored-by: Owncast <owncast@owncast.online>
Co-authored-by: Aaron Ogle <geekgonecrazy@users.noreply.github.com>

* Set webhook as used on completion. Closes #610

* Display webhook errors as errors

* Commit updated API documentation

* Add user joined chat event

* Change integration API paths. Update API spec

* Update development version of admin that supports integration apis

* Commit updated API documentation

* Add automated tests for external integration APIs

* check error

* quiet this test for now

* Route up some additional 3rd party apis. #638

* Commit updated API documentation

* Save username on user joined event

* Add missing scope to valid scopes list

* Add generic chat action event API for 3rd parties. Closes #666

* Commit updated API documentation

* First pass at moving WIP config framework into project for #234

* Only support exported fields in custom types

* Using YP get/set key as a first pass at using the data layer. Fixes + integration.

* Ignore test db

* Start adding getters and setters for config values

* More get/set config work. Starting to populate api with data

* Wire up some config edit endpoints

* More endpoints

* Disable cors middleware

* Add more endpoints and add test to test them

* Remove the in-memory change APIs

* Add endpoint for changing tags

* Add more config endpoints

* Starting to point more things away from config file and to the datastore

* Populate YP with db data

* Create new util method for parsing page body markdown and return it in api

* Verify proposed path to ffmpeg

* For development purposes show the config key in logs

* Move stats values to datastore

* Moving over more values to the datastore

* Move S3 config to datastore

* First pass the config -> db migrator

* Add the start of the video config apis

* It builds pointing everything away from the config

* Tweak ffmpeg path error message

* Backup database every hour. Closes #549

* Config + defaults + migration work for db

* Cleanup logging

* Remove all the old config structs

* Add descriptive info about migration

* Tweak ffmpeg validation logic

* Fix db backup path. backup on db version migration

* Set video and s3 configurations

* Update api spec with new config endpoints

* Add migrator for stats file

* Commit updated API documentation

* Use a dynamic system port for internal HLS writes. Closes #577 (#626)

* Use a dynamic system port for internal HLS writes. Closes #577

* Cleanup

* YP key migration to datastore

* Create a backup directory if needed before migrations

* Remove config test that no longer makes sense. Cleanup.

* Change number types from float32 to float64

* Update automated test suite

* Allow restoring a database backup via command line flags. Closes #549

* Add new hls segment config api

* Commit updated API documentation

* Update apis to require a value container property

* add socialHandles api

* Commit updated API documentation

* Add new latancy level setting to replace segment settings

* Commit updated API documentation

* Fix spelling

* Commit updated API documentation

* hardcode a json api of available social platforms

* Add additional icons

* Return social handles in server config api

* Add socialhandles validation to test

* Move list of hard coded social platforms to an api

* Remove audio only code from transcoder since we do not use it

* Add latency levels api + snapshot of video settings as current broadcast

* Add config/serverurl endpoint

* Return 404 on YP api if disabled

* Surface stream title in YP response

* Add stream title to web ui

* Cleanup log message. Closes #520

* Rename ffmpeg package to transcoder

* Add ws package for testing

* Reduce chat backlog to past 5hrs, max 50. Closes #548

* Fix error formatting

* Add endpoint for resetting yp registration

* Add yp/reset to api spec. return status in response

* Return zero viewer count if stream is offline. Closes #422

* Post-rebase fixes

* Fix merge conflict in openapi file

* Commit updated API documentation

* Standardize controller names

* Support setting the stream key via the command line. Closes #665

* Return social handles with YP data. First half of https://github.com/owncast/owncast-yp/issues/28

* Give the YP package access to server status regardless if enabled or not

* Change delay in automated tests

* Add stream title integration API. For #638

* Commit updated API documentation

* Add storage to the migrator

* Missing returning NSFW value in server config

* Add flag to ignore websocket client. Closes #537

* Add error for parsing broadcaster metadata

* Add support for a cli specified http server port. Closes #674

* Add cpu usage levels and a temporary mapping between it and libx264 presets

* Test for valid url endpoint when saving s3 config

* Re-configure storage on every stream to allow changing storage providers

* After 5 minutes of a stream being stopped clear the stream title

* Hide viewer count once stream goes offline instead of when player stops

* Pull steamTitle from the status that gets updated instead of the config

* Commit updated API documentation

* Optionally show stream title in the header

* Reset stream title when server starts

* Show chat action when stream title is updated

* Allow system messages to come back in persistence

* Split out getting chat history for moderation + fix tests

* Remove server title and standardize on name only

* Commit updated API documentation

* Bump github.com/aws/aws-sdk-go from 1.37.1 to 1.37.2 (#680)

Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.37.1 to 1.37.2.
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Changelog](https://github.com/aws/aws-sdk-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.37.1...v1.37.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add video variant and stream latency config file migrator

* Remove mostly unused disable upgrade check bool

* Commit updated API documentation

* Allow bundling the admin from the 0.0.6 branch

* Fix saving port numbers

* Use name instead of old title on window focus

* Work on latency levels. Fix test to use levels. Clean up transcoder to only reference levels

* Another place where title -> name

* Fix test

* Bump github.com/aws/aws-sdk-go from 1.37.2 to 1.37.3 (#690)

Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.37.2 to 1.37.3.
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Changelog](https://github.com/aws/aws-sdk-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.37.2...v1.37.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update dependabot config

* Bump github.com/aws/aws-sdk-go from 1.37.3 to 1.37.5 (#693)

Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.37.3 to 1.37.5.
- [Release notes](https://github.com/aws/aws-sdk-go/releases)
- [Changelog](https://github.com/aws/aws-sdk-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-go/compare/v1.37.3...v1.37.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump video.js from 7.10.2 to 7.11.4 in /build/javascript (#694)

* Bump video.js from 7.10.2 to 7.11.4 in /build/javascript

Bumps [video.js](https://github.com/videojs/video.js) from 7.10.2 to 7.11.4.
- [Release notes](https://github.com/videojs/video.js/releases)
- [Changelog](https://github.com/videojs/video.js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/videojs/video.js/compare/v7.10.2...v7.11.4)

Signed-off-by: dependabot[bot] <support@github.com>

* Commit updated Javascript packages

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Owncast <owncast@owncast.online>

* Make the latency migrator dynamic so I can tweak values easier

* Split out fetching ffmpeg path from validating the path so it can be changed in the admin

* Some commenting and linter cleanup

* Validate the path for a logo change and throw an error if it does not exist

* Logo change requests have to be a real file now

* Cleanup, making linter happy

* Format javascript on push

* Only format js in master

* Tweak latency level values

* Remove unused config file examples

* Fix thumbnail generation after messing with the ffmpeg path getter

* Reduce how often we report high hardware utilization warnings

* Bundle the 0.0.6 branch version of the admin

* Return validated ffmpeg path in admin server config

* Change the logo to be stored in the data directory instead of webroot

* Bump postcss from 8.2.4 to 8.2.5 in /build/javascript (#702)

Bumps [postcss](https://github.com/postcss/postcss) from 8.2.4 to 8.2.5.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.2.4...8.2.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Default config file no longer used

* don't show stream title when offline

addresses https://github.com/owncast/owncast/issues/677

* Remove auto-clearing stream title. #677

* webroot -> data when using logo as thumbnail

* Do not list websocket/access token create/delete as integration APIs

* Commit updated API documentation

* Bundle updated admin

* Remove pointing to the 0.0.6 admin branch

* Linter cleanup

* Linter cleanup

* Add donations and follow links to show up under social handles

* Prettified Code!

* More linter cleanup

* Update admin bundle

* Remove use of platforms.js and return icons with social handles. Closes #732

* Update admin bundle

* Support custom config path for use in migration

* Remove unused platform-logos.gif

* Reduce log level of message

* Remove unused logo files in static dir

* Handle dev vs. release build info

* Restore logo.png for initial thumbnail

* Cleanup some files from the build process that are not needed

* Fix incorrect build-time injection var

* Fix missing file getting copied to the build

* Remove console directory message.

* Update admin bundle

* Fix comment

* Report storage setup error

* add some value set error checking

* Use validated dynamic ffmpeg path for animated gif preview

* Make chat message links be white so they don't hide in the bg. Closes #599

* Restore conditional that was accidentally removed

Co-authored-by: Aaron Ogle <geekgonecrazy@users.noreply.github.com>
Co-authored-by: Owncast <owncast@owncast.online>
Co-authored-by: Ginger Wong <omqmail@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: nebunez <uoj2y7wak869@opayq.net>
Co-authored-by: gabek <gabek@users.noreply.github.com>
This commit is contained in:
Gabe Kangas
2021-02-18 23:05:52 -08:00
committed by GitHub
parent 05ec74a1e3
commit bc2caadb74
125 changed files with 5544 additions and 1510 deletions

View File

@@ -1,48 +1,12 @@
var request = require('supertest');
request = request('http://127.0.0.1:8080');
test('stream details are correct', (done) => {
request.get('/api/admin/status').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body.broadcaster.streamDetails.width).toBe(320);
expect(res.body.broadcaster.streamDetails.height).toBe(180);
expect(res.body.broadcaster.streamDetails.framerate).toBe(24);
expect(res.body.broadcaster.streamDetails.videoBitrate).toBe(1269);
expect(res.body.broadcaster.streamDetails.videoCodec).toBe('H.264');
expect(res.body.broadcaster.streamDetails.audioCodec).toBe('AAC');
expect(res.body.online).toBe(true);
done();
});
});
test('admin configuration is correct', (done) => {
request.get('/api/admin/serverconfig').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body.instanceDetails.name).toBe('Owncast');
expect(res.body.instanceDetails.title).toBe('Owncast');
expect(res.body.instanceDetails.summary).toBe('This is brief summary of whom you are or what your stream is. You can edit this description in your config file.');
expect(res.body.instanceDetails.logo).toBe('/img/logo.svg');
expect(res.body.instanceDetails.tags).toStrictEqual(['music', 'software', 'streaming']);
expect(res.body.videoSettings.segmentLengthSeconds).toBe(4);
expect(res.body.videoSettings.numberOfPlaylistItems).toBe(5);
expect(res.body.videoSettings.videoQualityVariants[0].framerate).toBe(24);
expect(res.body.videoSettings.videoQualityVariants[0].encoderPreset).toBe('veryfast');
expect(res.body.videoSettings.numberOfPlaylistItems).toBe(5);
expect(res.body.yp.enabled).toBe(false);
expect(res.body.streamKey).toBe('abc123');
done();
});
});
test('correct number of log entries exist', (done) => {
request.get('/api/admin/logs').auth('admin', 'abc123').expect(200)
.then((res) => {
// expect(res.body).toHaveLength(4);
// expect(res.body).toHaveLength(8);
done();
});
});

View File

@@ -5,7 +5,7 @@ request = request('http://127.0.0.1:8080');
const WebSocket = require('ws');
var ws;
const id = Math.random().toString(36).substring(7);
const testMessageId = Math.random().toString(36).substring(7);
const username = 'user' + Math.floor(Math.random() * 100);
const message = Math.floor(Math.random() * 100) + ' test 123';
const messageRaw = message + ' *and some markdown too*';
@@ -15,7 +15,7 @@ const date = new Date().toISOString();
const testMessage = {
author: username,
body: messageRaw,
id: id,
id: testMessageId,
type: 'CHAT',
visible: true,
timestamp: date,
@@ -37,12 +37,16 @@ test('can send a chat message', (done) => {
});
test('can fetch chat messages', (done) => {
request.get('/api/chat').expect(200)
request.get('/api/admin/chat/messages').auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body[0].author).toBe(testMessage.author);
expect(res.body[0].body).toBe(messageMarkdown);
expect(res.body[0].date).toBe(testMessage.date);
expect(res.body[0].type).toBe(testMessage.type);
const message = res.body.filter(function(msg) {
return msg.id = testMessageId;
})[0];
expect(message.author).toBe(testMessage.author);
expect(message.body).toBe(messageMarkdown);
expect(message.date).toBe(testMessage.date);
expect(message.type).toBe(testMessage.type);
done();
});

View File

@@ -31,7 +31,7 @@ test('can send a chat message', (done) => {
var messageId;
test('verify we can make API call to mark message as hidden', async (done) => {
const res = await request.get('/api/chat').expect(200);
const res = await request.get('/api/admin/chat/messages').auth('admin', 'abc123').expect(200)
const message = res.body[0];
messageId = message.id;
await request.post('/api/admin/chat/updatemessagevisibility')

View File

@@ -0,0 +1,191 @@
var request = require('supertest');
request = request('http://127.0.0.1:8080');
const serverName = randomString();
const streamTitle = randomString();
const serverSummary = randomString();
const pageContent = `<p>${randomString()}</p>`;
const tags = [randomString(), randomString(), randomString()];
const latencyLevel = Math.floor(Math.random() * 5 + 1);
const streamOutputVariants = {
videoBitrate: randomNumber() * 100,
framerate: 42,
cpuUsageLevel: 2,
scaledHeight: randomNumber() * 100,
scaledWidth: randomNumber() * 100,
};
const socialHandles = [
{
url: 'http://facebook.org/' + randomString(),
platform: randomString(),
},
];
const s3Config = {
enabled: true,
endpoint: 'http://' + randomString(),
accessKey: randomString(),
secret: randomString(),
bucket: randomString(),
region: randomString(),
};
test('set server name', async (done) => {
const res = await sendConfigChangeRequest('name', serverName);
done();
});
test('set stream title', async (done) => {
const res = await sendConfigChangeRequest('streamtitle', streamTitle);
done();
});
test('set server summary', async (done) => {
const res = await sendConfigChangeRequest('serversummary', serverSummary);
done();
});
test('set extra page content', async (done) => {
const res = await sendConfigChangeRequest('pagecontent', pageContent);
done();
});
test('set tags', async (done) => {
const res = await sendConfigChangeRequest('tags', tags);
done();
});
test('set latency level', async (done) => {
const res = await sendConfigChangeRequest(
'video/streamlatencylevel',
latencyLevel
);
done();
});
test('set video stream output variants', async (done) => {
const res = await sendConfigChangeRequest('video/streamoutputvariants', [
streamOutputVariants,
]);
done();
});
test('set social handles', async (done) => {
const res = await sendConfigChangeRequest('socialhandles', socialHandles);
done();
});
test('set s3 configuration', async (done) => {
const res = await sendConfigChangeRequest('s3', s3Config);
done();
});
test('verify updated config values', async (done) => {
const res = await request.get('/api/config');
expect(res.body.name).toBe(serverName);
expect(res.body.streamTitle).toBe(streamTitle);
expect(res.body.summary).toBe(serverSummary);
expect(res.body.extraPageContent).toBe(pageContent);
expect(res.body.logo).toBe('/logo');
expect(res.body.socialHandles).toStrictEqual(socialHandles);
done();
});
// Test that the raw video details being broadcasted are coming through
test('stream details are correct', (done) => {
request
.get('/api/admin/status')
.auth('admin', 'abc123')
.expect(200)
.then((res) => {
expect(res.body.broadcaster.streamDetails.width).toBe(320);
expect(res.body.broadcaster.streamDetails.height).toBe(180);
expect(res.body.broadcaster.streamDetails.framerate).toBe(24);
expect(res.body.broadcaster.streamDetails.videoBitrate).toBe(1269);
expect(res.body.broadcaster.streamDetails.videoCodec).toBe('H.264');
expect(res.body.broadcaster.streamDetails.audioCodec).toBe('AAC');
expect(res.body.online).toBe(true);
done();
});
});
test('admin configuration is correct', (done) => {
request
.get('/api/admin/serverconfig')
.auth('admin', 'abc123')
.expect(200)
.then((res) => {
expect(res.body.instanceDetails.name).toBe(serverName);
expect(res.body.instanceDetails.summary).toBe(serverSummary);
expect(res.body.instanceDetails.tags).toStrictEqual(tags);
expect(res.body.instanceDetails.socialHandles).toStrictEqual(
socialHandles
);
expect(res.body.videoSettings.latencyLevel).toBe(latencyLevel);
expect(res.body.videoSettings.videoQualityVariants[0].framerate).toBe(
streamOutputVariants.framerate
);
expect(res.body.videoSettings.videoQualityVariants[0].cpuUsageLevel).toBe(
streamOutputVariants.cpuUsageLevel
);
expect(res.body.yp.enabled).toBe(false);
expect(res.body.streamKey).toBe('abc123');
expect(res.body.s3.enabled).toBe(s3Config.enabled);
expect(res.body.s3.endpoint).toBe(s3Config.endpoint);
expect(res.body.s3.accessKey).toBe(s3Config.accessKey);
expect(res.body.s3.secret).toBe(s3Config.secret);
expect(res.body.s3.bucket).toBe(s3Config.bucket);
expect(res.body.s3.region).toBe(s3Config.region);
done();
});
});
test('frontend configuration is correct', (done) => {
request
.get('/api/config')
.expect(200)
.then((res) => {
expect(res.body.name).toBe(serverName);
expect(res.body.logo).toBe('/logo');
expect(res.body.socialHandles).toStrictEqual(socialHandles);
done();
});
});
async function sendConfigChangeRequest(endpoint, value) {
const url = '/api/admin/config/' + endpoint;
const res = await request
.post(url)
.auth('admin', 'abc123')
.send({ value: value })
.expect(200);
expect(res.body.success).toBe(true);
return res;
}
async function sendConfigChangePayload(endpoint, payload) {
const url = '/api/admin/config/' + endpoint;
const res = await request
.post(url)
.auth('admin', 'abc123')
.send(payload)
.expect(200);
expect(res.body.success).toBe(true);
return res;
}
function randomString(length = 20) {
return Math.random().toString(16).substr(2, length);
}
function randomNumber() {
return Math.floor(Math.random() * 5);
}

View File

@@ -8,14 +8,3 @@ test('service is online', (done) => {
done();
});
});
test('frontend configuration is correct', (done) => {
request.get('/api/config').expect(200)
.then((res) => {
expect(res.body.title).toBe('Owncast');
expect(res.body.logo).toBe('/img/logo.svg');
expect(res.body.socialHandles[0].platform).toBe('github');
expect(res.body.socialHandles[0].url).toBe('http://github.com/owncast/owncast');
done();
});
});

View File

@@ -0,0 +1,109 @@
var request = require('supertest');
request = request('http://127.0.0.1:8080');
var accessToken = '';
var webhookID;
const webhook = 'https://super.duper.cool.thing.biz/owncast';
const events = ['CHAT'];
test('create webhook', async (done) => {
const res = await sendIntegrationsChangePayload('webhooks/create', {
url: webhook,
events: events,
});
expect(res.body.url).toBe(webhook);
expect(res.body.timestamp).toBeTruthy();
expect(res.body.events).toStrictEqual(events);
done();
});
test('check webhooks', (done) => {
request.get('/api/admin/webhooks')
.auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body).toHaveLength(1);
expect(res.body[0].url).toBe(webhook);
expect(res.body[0].events).toStrictEqual(events);
webhookID = res.body[0].id;
done();
});
});
test('delete webhook', async (done) => {
const res = await sendIntegrationsChangePayload('webhooks/delete', {
id: webhookID,
});
expect(res.body.success).toBe(true);
done();
});
test('check that webhook was deleted', (done) => {
request.get('/api/admin/webhooks')
.auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body).toHaveLength(0);
done();
});
});
test('create access token', async (done) => {
const name = 'test token';
const scopes = ['CAN_SEND_SYSTEM_MESSAGES'];
const res = await sendIntegrationsChangePayload('accesstokens/create', {
name: name,
scopes: scopes,
});
expect(res.body.token).toBeTruthy();
expect(res.body.timestamp).toBeTruthy();
expect(res.body.name).toBe(name);
expect(res.body.scopes).toStrictEqual(scopes);
accessToken = res.body.token;
done();
});
test('check access tokens', (done) => {
request.get('/api/admin/accesstokens')
.auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body).toHaveLength(1);
expect(res.body[0].token).toBe(accessToken);
done();
});
});
test('send a system message using access token', async (done) => {
const payload = {body: 'test 1234'};
const res = await request.post('/api/integrations/chat/system')
.set('Authorization', 'Bearer ' + accessToken)
.send(payload).expect(200);
done();
});
test('delete access token', async (done) => {
const res = await sendIntegrationsChangePayload('accesstokens/delete', {
token: accessToken,
});
expect(res.body.success).toBe(true);
done();
});
test('check token delete was successful', (done) => {
request.get('/api/admin/accesstokens')
.auth('admin', 'abc123').expect(200)
.then((res) => {
expect(res.body).toHaveLength(0);
done();
});
});
async function sendIntegrationsChangePayload(endpoint, payload) {
const url = '/api/admin/' + endpoint;
const res = await request.post(url)
.auth('admin', 'abc123')
.send(payload).expect(200);
return res
}

View File

@@ -19,7 +19,7 @@ pushd ../.. > /dev/null
# Build and run owncast from source
go build -o owncast main.go pkged.go
./owncast -database $TEMP_DB -configFile config-default.yaml &
./owncast -database $TEMP_DB &
SERVER_PID=$!
popd > /dev/null
@@ -27,7 +27,7 @@ sleep 5
# Start streaming the test file over RTMP to
# the local owncast instance.
ffmpeg -hide_banner -loglevel panic -re -i test.mp4 -vcodec libx264 -profile:v main -sc_threshold 0 -b:v 1300k -acodec copy -f flv rtmp://127.0.0.1/live/abc123 &
ffmpeg -hide_banner -loglevel panic -stream_loop -1 -re -i test.mp4 -vcodec libx264 -profile:v main -sc_threshold 0 -b:v 1300k -acodec copy -f flv rtmp://127.0.0.1/live/abc123 &
FFMPEG_PID=$!
function finish {
@@ -37,7 +37,7 @@ function finish {
trap finish EXIT
echo "Waiting..."
sleep 15
sleep 13
# Run the tests against the instance.
npm test

27
test/package-lock.json generated
View File

@@ -6,7 +6,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
"requires": {
"object-keys": "^1.0.12"
}
@@ -15,7 +14,6 @@
"version": "1.17.6",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
"integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
@@ -34,7 +32,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@@ -44,14 +41,12 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
@@ -59,26 +54,22 @@
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
"dev": true
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"is-callable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
"integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
"dev": true
"integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
},
"is-date-object": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
"dev": true
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
"integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
"dev": true,
"requires": {
"has-symbols": "^1.0.1"
}
@@ -87,7 +78,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"dev": true,
"requires": {
"has-symbols": "^1.0.1"
}
@@ -95,20 +85,17 @@
"object-inspect": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
"dev": true
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
"dev": true,
"requires": {
"define-properties": "^1.1.2",
"function-bind": "^1.1.1",
@@ -120,7 +107,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
@@ -130,7 +116,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"