Giter VIP home page Giter VIP logo

egress's Introduction

The LiveKit icon, the name of the repository and some sample code in the background.

LiveKit Egress

WebRTC is fantastic for last-mile media delivery, but interoperability with other services can be challenging. An application may want to do things like store a session for future playback, relay a stream to a CDN, or process a track through a transcription service – workflows where media travels through a different system or protocol. LiveKit Egress is the solution to these interoperability challenges. It provides a consistent set of APIs that gives you universal export of your LiveKit sessions and tracks.

Capabilities

  1. Room composite for exporting an entire room.
  2. Web egress for recordings that aren't attached to a single LiveKit room.
  3. Track composite for exporting synchronized tracks of a single participant.
  4. Track egress for exporting individual tracks.

Depending on your request type, the egress service will either launch Chrome using a web template (room composite requests) or a supplied url (web requests), or it will use the Go SDK directly (track and track composite requests). Irrespective of method used, when moving between protocols, containers or encodings, LiveKit's egress service will automatically transcode streams for you using GStreamer.

Supported Output

Egress Type MP4 File OGG File WebM File HLS (TS Segments) RTMP(s) Stream WebSocket Stream Thumbnails (JPEGs)
Room Composite
Web
Track Composite
Track

Files can be uploaded to any S3 compatible storage, Azure, or GCP.

Documentation

Full docs available here

Config

The Egress service takes a yaml config file:

# required fields
api_key: livekit server api key. LIVEKIT_API_KEY env can be used instead
api_secret: livekit server api secret. LIVEKIT_API_SECRET env can be used instead
ws_url: livekit server websocket url. LIVEKIT_WS_URL can be used instead
redis:
  address: must be the same redis address used by your livekit server
  username: redis username
  password: redis password
  db: redis db

# optional fields
health_port: port used for http health checks (default 0)
template_port: port used to host default templates (default 7980)
prometheus_port: port used to collect prometheus metrics (default 0)
debug_handler_port: port used to host http debug handlers (default 0)
logging:
  level: debug, info, warn, or error (default info)
  json: true
template_base: can be used to host custom templates (default http://localhost:<template_port>/)
backup_storage: files will be moved here when uploads fail. location must have write access granted for all users
enable_chrome_sandbox: if true, egress will run Chrome with sandboxing enabled. This requires a specific Docker setup, see below.
cpu_cost: # optionally override cpu cost estimation, used when accepting or denying requests
  room_composite_cpu_cost: 3.0
  web_cpu_cost: 3.0
  track_composite_cpu_cost: 2.0
  track_cpu_cost: 1.0
session_limits: # optional egress duration limits - once hit, egress will end with status EGRESS_LIMIT_REACHED
  file_output_max_duration: 1h
  stream_output_max_duration: 90m
  segment_output_max_duration: 3h

# file upload config - only one of the following. Can be overridden per request
s3:
  access_key: AWS_ACCESS_KEY_ID env or IAM role can be used instead
  secret: AWS_SECRET_ACCESS_KEY env or IAM role can be used instead
  region: AWS_DEFAULT_REGION env or IAM role can be used instead
  endpoint: (optional) custom endpoint
  bucket: bucket to upload files to
  # the following s3 options can only be set in config, *not* per request, they will be added to any per-request options
  proxy_config:
    url: (optional) proxy url
    username: (optional) proxy username
    password: (optional) proxy password
  max_retries: (optional, default=3) number or retries to attempt
  max_retry_delay: (optional, default=5s) max delay between retries (e.g. 5s, 100ms, 1m...)
  min_retry_delay: (optional, default=500ms) min delay between retries (e.g. 100ms, 1s...)
  aws_log_level: (optional, default=LogOff) log level for aws sdk (LogDebugWithRequestRetries, LogDebug, ...) 
azure:
  account_name: AZURE_STORAGE_ACCOUNT env can be used instead
  account_key: AZURE_STORAGE_KEY env can be used instead
  container_name: container to upload files to
gcp:
  credentials_json: GOOGLE_APPLICATION_CREDENTIALS env can be used instead
  bucket: bucket to upload files to
  proxy_config:
    url: (optional) proxy url
    username: (optional) proxy username
    password: (optional) proxy password
alioss:
  access_key: Ali OSS AccessKeyId
  secret: Ali OSS AccessKeySecret
  region: Ali OSS region
  endpoint: (optional) custom endpoint
  bucket: bucket to upload files to

# dev/debugging fields
insecure: can be used to connect to an insecure websocket (default false)
debug:
  enable_profiling: create and upload pipeline dot file and pprof file on pipeline failure
  s3: upload config for dotfiles (see above)
  azure: upload config for dotfiles (see above)
  gcp: upload config for dotfiles (see above)
  alioss: upload config for dotfiles (see above)

The config file can be added to a mounted volume with its location passed in the EGRESS_CONFIG_FILE env var, or its body can be passed in the EGRESS_CONFIG_BODY env var.

Filenames

The below templates can also be used in filename/filepath parameters:

Egress Type {room_id} {room_name} {time} {utc} {publisher_identity} {track_id} {track_type} {track_source}
Room Composite
Web
Track Composite
Track
  • If no filename is provided with a request, one will be generated in the form of "{room_name}-{time}".
  • If your filename ends with a /, a file will be generated in that directory.
  • For 1/2/2006, 3:04:05.789 PM, {time} format would display "2006-01-02T150405", and {utc} format "20060102150405789"

Examples:

Request filename Resulting filename
"" testroom-2022-10-04T011306.mp4
"livekit-recordings/" livekit-recordings/testroom-2022-10-04T011306.mp4
"{room_name}/{time}" testroom/2022-10-04T011306.mp4
"{room_id}-{publisher_identity}.mp4" 10719607-f7b0-4d82-afe1-06b77e91fe12-david.mp4
"{track_type}-{track_source}-{track_id}" audio-microphone-TR_SKasdXCVgHsei.ogg

Running locally

These changes are not recommended for a production setup.

To run against a local livekit server, you'll need to do the following:

  • open /usr/local/etc/redis.conf and comment out the line that says bind 127.0.0.1
  • change protected-mode yes to protected-mode no in the same file
  • find your IP as seen by docker
    • ws_url needs to be set using the IP as Docker sees it
    • on linux, this should be 172.17.0.1
    • on mac or windows, run docker run -it --rm alpine nslookup host.docker.internal and you should see something like Name: host.docker.internal Address: 192.168.65.2

These changes allow the service to connect to your local redis instance from inside the docker container.

Create a directory to mount. In this example, we will use ~/egress-test.

Create a config.yaml in the above directory.

  • redis and ws_url should use the above IP instead of localhost
  • insecure should be set to true
log_level: debug
api_key: your-api-key
api_secret: your-api-secret
ws_url: ws://192.168.65.2:7880
insecure: true
redis:
  address: 192.168.65.2:6379

Then to run the service:

docker run --rm \
    -e EGRESS_CONFIG_FILE=/out/config.yaml \
    -v ~/egress-test:/out \
    livekit/egress

You can then use our cli to submit egress requests to your server.

Chrome sandboxing

By default, Room Composite and Web egresses run with Chrome sandboxing disabled. This is because the default docker security settings prevent Chrome from switching to a different kernel namespace, which is needed by Chrome to setup its sandbox.

Chrome sandboxing within Egress can be reenabled by setting the the enable_chrome_sandbox option to true in the egress configuration, and launching docker using the provided seccomp security profile:

docker run --rm \
    -e EGRESS_CONFIG_FILE=/out/config.yaml \
    -v ~/egress-test:/out \
    --security-opt seccomp=chrome-sandboxing-seccomp-profile.json \
    livekit/egress

This profile is based on the default docker seccomp security profile and allows the 2 extra system calls (clone and unshare) that Chrome needs to setup the sandbox.

Note that kubernetes disables seccomp entirely by default, which means that running with Chrome sandboxing enabled is possible on a kubernetes cluster with the default security settings.

FAQ

Can I store the files locally instead of uploading to cloud storage?

  • Yes, you can mount a volume with your docker run command (e.g. -v ~/livekit-egress:/out/), and use the mounted directory in your filenames (e.g. /out/my-recording.mp4). Since egress is not run as the root user, write permissions will need to be enabled for all users.

I get a "no response from egress service" error when sending a request

  • Your livekit server cannot connect to an egress instance through redis. Make sure they are both able to reach the same redis db.
  • If all of your egress instances are full, you'll need to deploy more instances or set up autoscaling.

I get a different error when sending a request

  • Make sure your egress, livekit, server sdk, and livekit-cli are all up to date.

Can I run this without docker?

  • It's possible, but not recommended. To do so, you would need to install gstreamer along with its plugins, chrome, xvfb, and have a pulseaudio server running.

Testing and Development

To run the test against your own LiveKit rooms, a deployed LiveKit server with a secure websocket url is required. First, create egress/test/config.yaml:

log_level: debug
api_key: your-api-key
api_secret: your-api-secret
ws_url: wss://your-livekit-url.com
redis:
  address: 192.168.65.2:6379
room_only: false
web_only: false
track_composite_only: false
track_only: false
file_only: false
stream_only: false
segments_only: false
muting: false
dot_files: false
short: false

Join a room using https://example.livekit.io or your own client, then run mage integration test/config.yaml. This will test recording different file types, output settings, and streams against your room.


LiveKit Ecosystem
Real-time SDKsReact Components · Browser · iOS/macOS · Android · Flutter · React Native · Rust · Node.js · Python · Unity (web) · Unity (beta)
Server APIsNode.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (community)
Agents FrameworksPython · Playground
ServicesLivekit server · Egress · Ingress · SIP
ResourcesDocs · Example apps · Cloud · Self-hosting · CLI

egress's People

Contributors

alex-bluetrain avatar biglittlebigben avatar cruizba avatar cscherban avatar ct7t avatar dandoug avatar davidzhao avatar dwirya avatar frostbyte73 avatar lukasio avatar nkonev avatar ocupe avatar onthegit avatar paulwe avatar real-danm avatar renovate[bot] avatar rrampage avatar spennihana avatar tomxiong avatar vladlensb 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

egress's Issues

Strange behaviour of the websocket egress bitrate when microphone is reduced

The regular situation

When publishing audio with the livekit-cli publish capability and starting a websocket egress, I measure a bitrate of 192kB/s on the receiving side. This is exactly what we would expect as

48 kHz sample rate * 2 bytes per sample * 2 channels = 192kB/s

The rate oscillate around this value.

Screen.Recording.2022-10-20.at.17.48.34.mov

The weird situation

Now when the audio is published via the js client, on chrome on mac, if I reduce the microphone the bitrate suddenly decreases to around 20kB/s. The following video shows the behavior:

Screen.Recording.2022-10-20.at.18.11.08.mov.mp4

Expected situation

The bitrate is constant, or some mute event is sent.

Config:

Macbook pro M1
Chrome 106.0
livekit client js 1.1.7
livekit server: 1.2.1
livekit egress: 1.4.0

Allow Egress to Be Configured to Save Track Metadata

When recording tracks, often additional information is required to be able to make use of the tracks for transcription, compositing, etc. If egress could be configured to drop down a .json file with some track information next to the track, it would be very useful, as some of these scenarios can't be accomplished with knowing some basic information like the offset of the track from the start (in relation to the other tracks in the room), the track info (id, name, source, etc.), participant info, the room info.

In the future, this metadata could be used by a recordings service to allow enumerating recordings for a room along with some basic metadata about the tracks.

Negative duration in EgressInfo.File?

Looking at the below EgressInfo returned from a egress_ended event, the duration property seems to be consistently negative. It seems that it maybe for convenience where I'd have start_time + (-1653767466240974001) == absolute_duration, for example, but I'm not sure, as I'm used to a duration being positive number. Can you please clarify?

file {
  filename: "video.mp4"
  size: 39657693
  location: "https://somewhere-out-there.mp4"
  duration: -1653767466240974001
}

Can we update gstreamer to 1.20.4?

GStreamer 1.20.4 stable bug fix release:
matroska-mux: also allow width + height changes for avc3|hev1|vp8|vp9

{"level":"error","ts":1665983528.9609885,"logger":"egress","caller":"pipeline/pipeline.go:734","msg":"pipeline error","nodeID":"NE_Ly4GjPApXo78","egressID":"EG_tSXrjvsSuF55","debug":"../gst/matroska/matroska-mux.c(1111): gst_matroska_mux_video_pad_setcaps (): /GstPipeline:pipeline/GstBin:input/GstWebMMux:webmmux0:\nCaps changes are not supported by Matroska\nCurrent: video/x-vp8, framerate=(fraction)0/1, height=(int)540, width=(int)960, profile=(string)0\nNew: video/x-vp8, framerate=(fraction)0/1, height=(int)720, width=(int)1280, profile=(string)0","message":"Could not multiplex stream.","error":"Could not multiplex stream.","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).handleError\n\t/workspace/pkg/pipeline/pipeline.go:734\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).messageWatch\n\t/workspace/pkg/pipeline/pipeline.go:289\ngithub.com/tinyzimmer/go-gst/gst.goBusFunc\n\t/root/go/pkg/mod/github.com/livekit/[email protected]/gst/cgo_exports.go:128\n_cgoexp_752bbda710ba_goBusFunc\n\t_cgo_gotypes.go:17363\nruntime.cgocallbackg1\n\t/usr/lib/go-1.18/src/runtime/cgocall.go:314\nruntime.cgocallbackg\n\t/usr/lib/go-1.18/src/runtime/cgocall.go:233\nruntime.cgocallback\n\t/usr/lib/go-1.18/src/runtime/asm_amd64.s:971\nruntime.systemstack_switch\n\t/usr/lib/go-1.18/src/runtime/asm_amd64.s:436\nruntime.cgocall\n\t/usr/lib/go-1.18/src/runtime/cgocall.go:167\ngithub.com/tinyzimmer/go-glib/glib._Cfunc_g_main_loop_run\n\t_cgo_gotypes.go:2822\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run.func1\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).Run\n\t/workspace/pkg/pipeline/pipeline.go:218\ngithub.com/livekit/egress/pkg/service.(*Handler).HandleRequest.func2\n\t/workspace/pkg/service/handler.go:58"}

Will this release fix this problem?

Egress pods on crashloopbackoff with `open /sys/fs/cgroup/cpu.stat: no such file or directory` on EKS

The change done in #144 is causing the pod's to crash on startup with the following log message:

+ export TMPDIR=/tmp/lkegress
+ TMPDIR=/tmp/lkegress
+ rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse
+ pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit
W: [pulseaudio] main.c: Running in system mode, but --disallow-module-loading not set.
N: [pulseaudio] main.c: Running in system mode, forcibly disabling SHM mode.
I: [pulseaudio] main.c: Daemon startup successful.
+ '[' -z /tmp/lkegress ']'
+ mkdir -p /tmp/lkegress
+ exec egress
{"level":"info","ts":1666453820.91946,"logger":"egress","caller":"redis/redis.go:53","msg":"connecting to redis","nodeID":"NE_nopW5aQoMiJ4","sentinel":false,"addr":"lr.abcdef.ng.0001.euw1.cache.amazonaws.com:6379"}
open /sys/fs/cgroup/cpu.stat: no such file or directory

I'm running egress on AWS EKS, with c7g.4xlarge instances and Bottlerocket AMI.

I forked the repo, reverted this PR, tested it and can confirm that it works without that change.

The number of channels of websocket streaming is not enforced.

Currently nothing seems to enforce that the PCMs that the websocket egress outputs have 2 channels (aka is stereo).
This information is needed for the PCM to be used reliably (for e.g. speech to text), otherwise the PCM might be badly interpreted (typically if using mono, it will be interpreted with a 2x speed).

As discussed offline with @frostbyte73 and @davidzhao, the simplest solution would be to enforce it during the conversion from original encoding to raw PCM.

No TLS support for Redis

Pretty much what it says in the title.

Request is just to add a useTLS flag to the helm chart and pass that through to the client so that we can securely connect to redis.

Failed to upload on S3

The egress failed to upload file on S3.
It is working with local file recording.

Here are the logs of both livekit and livekit egress since the only error I see is a disconnection of the websocket between egress and server.

Note: The error is also present when the record is saved in a local file and the result is ok and readable.

crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.029736,"logger":"egress","caller":"service/service.go:207","msg":"request accepted","nodeID":"NE_t8h2yDvqAoD5","egressID":"EG_8FxKtwP6RktB","requestID":"RPC_V3qUdHJ8b7B5","senderID":"ND_sMC3sDbO"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.0563405,"logger":"egress","caller":"server/main.go:125","msg":"setting TMPDIR environment and creating path","nodeID":"NE_Gat8uhLa4JsN","path":"/tmp/lkegress/EG_8FxKtwP6RktB"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.0565667,"logger":"egress","caller":"redis/redis.go:53","msg":"connecting to redis","nodeID":"NE_Gat8uhLa4JsN","sentinel":false,"addr":"crane-redis:6379"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.065Z        INFO    livekit service/roommanager.go:254      starting RTC session    {"room": "TEST10", "nodeID": "ND_sMC3sDbO", "participant": "EG_8FxKtwP6RktB", "sdk": "GO", "sdkVersion": "0.10.2", "protocol": 8}
crane-crane-livekit-1         | 2022-10-04T10:05:27.066Z        INFO    livekit rtc/room.go:287 new participant joined  {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "pID": "PA_omRkEiN7aQWq", "participant": "EG_8FxKtwP6RktB", "protocol": 8, "options": {"AutoSubscribe":false}}
crane-crane-livekit-1         | 2022-10-04T10:05:27.067Z        INFO    livekit service/rtcservice.go:238       new client WS connected {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "remote": false, "connID": "CO_N5A62mvXadWo"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.069Z        INFO    livekit rtc/transport.go:439    ice gathering state change      {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "gathering"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.0721729,"logger":"egress","caller":"[email protected]/signalclient.go:220","msg":"received offer for subscriber","nodeID":"NE_Gat8uhLa4JsN"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.069Z        INFO    livekit rtc/participant.go:1209 sending offer   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.080088,"logger":"egress","caller":"[email protected]/peerconnection.go:478","msg":"ICE connected","nodeID":"NE_Gat8uhLa4JsN"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.069Z        INFO    livekit rtc/participant_signal.go:142   sending ice candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "candidate": "udp4 host 192.168.1.47:7882", "target": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.070Z        INFO    livekit rtc/participant_signal.go:142   sending ice candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "candidate": "tcp4 host 192.168.1.47:7881", "target": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.076Z        INFO    livekit rtc/transportmanager.go:391     received answer {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.076Z        INFO    livekit rtc/transport.go:1438   add candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "candidate": "candidate:668435530 1 udp 2130706431 172.18.0.5 56648 typ host"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.077Z        INFO    livekit rtc/transport.go:473    ice connection state change     {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "checking"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.080Z        INFO    livekit rtc/transport.go:473    ice connection state change     {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "connected"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.081Z        INFO    livekit rtc/transport.go:480    selected ICE candidate pair     {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "pair": "(local) udp4 host 192.168.1.47:7882 <-> (remote) udp4 host 172.18.0.5:56648"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.083Z        INFO    livekit rtc/participant.go:2033 queuing subscribe       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.083Z        INFO    livekit rtc/signalhandler.go:49 updated subscription    {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "tracks": [], "subscribe": true}
crane-crane-livekit-1         | 2022-10-04T10:05:27.083Z        INFO    livekit rtc/participant.go:951  added subscribedTrack   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "publisherID": "PA_yjHRgdyacvXw", "publisherIdentity": "TEST10", "trackID": "TR_VCNP8cfzQd65T2"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.087Z        INFO    livekit rtc/transport.go:486    peer connection state change    {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "connected"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.087Z        INFO    livekit rtc/transport.go:1447   ice candidates  {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "lc": ["udp4 host 192.168.1.47:7882", "tcp4 host 192.168.1.47:7881"], "rc": ["candidate:668435530 1 udp 2130706431 172.18.0.5 56648 typ host"], "lc (filtered)": [], "rc (filtered)": []}
crane-crane-livekit-1         | 2022-10-04T10:05:27.116Z        INFO    livekit rtc/participant_signal.go:142   sending ice candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "candidate": "udp4 srflx 82.64.235.34:60127 related 0.0.0.0:37040", "target": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.117Z        INFO    livekit rtc/transport.go:1438   add candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "candidate": "candidate:4269779443 1 udp 1694498815 82.64.235.34 61840 typ srflx raddr 0.0.0.0 rport 49664"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.146Z        INFO    livekit rtc/transport.go:439    ice gathering state change      {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "complete"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.146Z        INFO    livekit rtc/participant_signal.go:142   sending ice candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "candidate": "udp4 srflx 82.64.235.34:59297 related 0.0.0.0:33496", "target": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.154Z        INFO    livekit rtc/transport.go:1438   add candidate   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "candidate": "candidate:4269779443 1 udp 1694498815 82.64.235.34 55775 typ srflx raddr 0.0.0.0 rport 35234"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.234Z        INFO    livekit rtc/participant.go:1209 sending offer   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.237Z        INFO    livekit rtc/transportmanager.go:391     received answer {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.237Z        INFO    livekit sfu/forwarder.go:314    setting max spatial layer       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "layer": 0}
crane-crane-livekit-1         | 2022-10-04T10:05:27.237Z        INFO    livekit rtc/dynacastquality.go:61       setting subscriber max quality  {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "TEST10", "pID": "PA_yjHRgdyacvXw", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "mime": "video/H264", "subscriberID": "PA_omRkEiN7aQWq", "quality": "HIGH"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.2350676,"logger":"egress","caller":"[email protected]/signalclient.go:220","msg":"received offer for subscriber","nodeID":"NE_Gat8uhLa4JsN"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.257Z        INFO    livekit sfu/forwarder.go:1491   locking to target layer {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "current": "VideoLayer{s: -1, t: -1}", "target": "VideoLayer{s: 0, t: 0}"}
crane-crane-livekit-1         | 2022-10-04T10:05:27.257Z        INFO    livekit rtc/dynacastquality.go:61       setting subscriber max quality  {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "TEST10", "pID": "PA_yjHRgdyacvXw", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "mime": "video/H264", "subscriberID": "PA_omRkEiN7aQWq", "quality": "HIGH"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.257608,"logger":"egress","caller":"[email protected]/room.go:246","msg":"track subscribed","nodeID":"NE_Gat8uhLa4JsN","participant":"TEST10","track":{},"kind":{}}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877927.849064,"logger":"egress","caller":"service/handler.go:129","msg":"egress updated","nodeID":"NE_Gat8uhLa4JsN","egressID":"EG_8FxKtwP6RktB","status":"EGRESS_ACTIVE"}
crane-crane-livekit-1         | 2022-10-04T10:05:28.166Z        INFO    livekit rtc/signalhandler.go:61 updated subscribed track settings       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "179658989674430465-72064c83-c903-4ecc-ad88-adc89e69675c", "pID": "PA_TQxKBRiip98i", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "settings": "track_sids:\"TR_VCNP8cfzQd65T2\"  disabled:true  quality:HIGH"}
crane-crane-livekit-1         | 2022-10-04T10:05:28.166Z        INFO    livekit rtc/signalhandler.go:61 updated subscribed track settings       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "179658989674430465-72064c83-c903-4ecc-ad88-adc89e69675c", "pID": "PA_TQxKBRiip98i", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "settings": "track_sids:\"TR_VCNP8cfzQd65T2\"  quality:HIGH"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877935.4393854,"logger":"egress","caller":"service/handler.go:129","msg":"egress updated","nodeID":"NE_Gat8uhLa4JsN","egressID":"EG_8FxKtwP6RktB","status":"EGRESS_ENDING"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.563Z        INFO    livekit rtc/signalhandler.go:71 client leaving room     {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false}
crane-crane-livekit-1         | 2022-10-04T10:05:35.564Z        INFO    livekit service/rtcservice.go:216       finishing WS connection {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "remote": false, "connID": "CO_N5A62mvXadWo"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.564Z        INFO    livekit rtc/room.go:393 closing participant for removal {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "pID": "PA_omRkEiN7aQWq", "participant": "EG_8FxKtwP6RktB"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.564Z        INFO    livekit rtc/participant.go:640  try close participant   {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "sendLeave": true, "reason": "CLIENT_REQUEST_LEAVE"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.564Z        INFO    livekit service/rtcservice.go:254       source closed connection        {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "remote": false, "connID": "CO_N5A62mvXadWo"}
crane-crane-livekit-egress-1  | {"level":"error","ts":1664877935.5642624,"logger":"egress","caller":"runtime/asm_amd64.s:1571","msg":"error with read worker","nodeID":"NE_Gat8uhLa4JsN","error":"read tcp 172.18.0.5:43414->172.18.0.6:7880: use of closed network connection","stacktrace":"runtime.goexit\n\t/usr/lib/go-1.18/src/runtime/asm_amd64.s:1571"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.565Z        INFO    livekit rtc/participant_signal.go:199   closing signal connection       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false}
crane-crane-livekit-1         | 2022-10-04T10:05:35.566Z        INFO    livekit sfu/downtrack.go:665    close down track        {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "flushBlankFrame": true}
crane-crane-livekit-1         | 2022-10-04T10:05:35.566Z        INFO    livekit sfu/forwarder.go:288    setting mute    {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "muted": true}
crane-crane-livekit-1         | 2022-10-04T10:05:35.571Z        INFO    livekit service/roommanager.go:433      RTC session finishing   {"participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "room": "TEST10", "roomID": "RM_kk9dDS2PDB2w"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.764Z        INFO    livekit sfu/downtrack.go:696    rtp stats       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "direction": "downstream", "stats": "t: Tue Oct  4 10:05:27 UTC 2022|Tue Oct  4 10:05:35 UTC 2022|8.51s sn: 48907|51779, ep: 2873|337.74/s, p: 2873|337.74/s, l: 0|0.0/s|0.00%, b: 821825|772891.0bps|57460, f: 256|30.1/s / 5|Tue Oct  4 10:05:35 UTC 2022, d: 0|0.00/s, bd: 0|0.0bps|0, pp: 0|0.00/s, bp: 0|0.0bps|0, o: 0, c: 90000, j: 120(1333.3us)|171(1900.0us), n:0|0|0|0, pli:0|Mon Jan  1 00:00:00 UTC 0001 / 1|Tue Oct  4 10:05:27 UTC 2022, fir:0|Mon Jan  1 00:00:00 UTC 0001, rtt(ms):4|5"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.764Z        INFO    livekit rtc/dynacastquality.go:61       setting subscriber max quality  {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "TEST10", "pID": "PA_yjHRgdyacvXw", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "mime": "video/H264", "subscriberID": "PA_omRkEiN7aQWq", "quality": "OFF"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.764Z        INFO    livekit rtc/participant.go:993  removed subscribedTrack {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "publisherID": "PA_yjHRgdyacvXw", "publisherIdentity": "TEST10", "trackID": "TR_VCNP8cfzQd65T2", "kind": "video"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.764Z        INFO    livekit rtc/transport.go:1292   leaving events processor        {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "PUBLISHER"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.765Z        INFO    livekit rtc/transport.go:486    peer connection state change    {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "PUBLISHER", "state": "closed"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.765Z        INFO    livekit rtc/transport.go:1292   leaving events processor        {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.765Z        INFO    livekit rtc/transport.go:486    peer connection state change    {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "closed"}
crane-crane-livekit-1         | 2022-10-04T10:05:35.765Z        INFO    livekit rtc/transport.go:473    ice connection state change     {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "EG_8FxKtwP6RktB", "pID": "PA_omRkEiN7aQWq", "remote": false, "transport": "SUBSCRIBER", "state": "closed"}
crane-crane-livekit-1         | 2022-10-04T10:05:36.007Z        INFO    livekit rtc/signalhandler.go:61 updated subscribed track settings       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "179658989674430465-72064c83-c903-4ecc-ad88-adc89e69675c", "pID": "PA_TQxKBRiip98i", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "settings": "track_sids:\"TR_VCNP8cfzQd65T2\"  disabled:true  quality:HIGH"}
crane-crane-livekit-1         | 2022-10-04T10:05:36.007Z        INFO    livekit rtc/signalhandler.go:61 updated subscribed track settings       {"room": "TEST10", "roomID": "RM_kk9dDS2PDB2w", "participant": "179658989674430465-72064c83-c903-4ecc-ad88-adc89e69675c", "pID": "PA_TQxKBRiip98i", "remote": false, "trackID": "TR_VCNP8cfzQd65T2", "settings": "track_sids:\"TR_VCNP8cfzQd65T2\"  quality:HIGH"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877947.3226297,"logger":"egress","caller":"service/handler.go:127","msg":"egress completed","nodeID":"NE_Gat8uhLa4JsN","egressID":"EG_8FxKtwP6RktB"}
crane-crane-livekit-1         | 2022-10-04T10:05:47.324Z        INFO    livekit service/egress.go:277   egress ended    {"egressID": "EG_8FxKtwP6RktB"}
crane-crane-livekit-egress-1  | {"level":"info","ts":1664877947.3327703,"logger":"egress","caller":"service/service.go:265","msg":"deleting handler temporary directory","nodeID":"NE_t8h2yDvqAoD5","path":"/tmp/lkegress/EG_8FxKtwP6RktB"}

Error while streaming: Blank black screen is being streamed no any track is being streamed???

{"level":"info","ts":1654778433.1441662,"logger":"egress","caller":"messaging/bus.go:16","msg":"connecting to redis work queue","nodeID":"NE_EgMpXPasfzmW","addr":"192.168.11.233:6379"}
{"level":"info","ts":1654778517.7863948,"logger":"egress","caller":"service/service.go:302","msg":"egress updated","nodeID":"NE_EgMpXPasfzmW","egressID":"EG_Tse7rFy7EZSY","status":"EGRESS_ENDING"}
{"level":"error","ts":1654778518.8913512,"logger":"egress","caller":"pipeline/pipeline.go:404","msg":"failed to parse pipeline error","nodeID":"NE_EgMpXPasfzmW","egressID":"EG_Tse7rFy7EZSY","debug":"../gst/rtmp2/gstrtmp2sink.c(1089): error_callback (): /GstPipeline:pipeline/GstBin:output/GstRtmp2Sink:sink_Vpt2m7HistAF","error":"Connection error","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).handleError\n\t/workspace/pkg/pipeline/pipeline.go:404\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).messageWatch\n\t/workspace/pkg/pipeline/pipeline.go:335\ngithub.com/tinyzimmer/go-gst/gst.goBusFunc\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/gst/cgo_exports.go:128\n_cgoexp_cb8cacfb8eb1_goBusFunc\n\t_cgo_gotypes.go:17347\nruntime.cgocallbackg1\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:292\nruntime.cgocallbackg\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:228\nruntime.cgocallback\n\t/usr/lib/go-1.16/src/runtime/asm_amd64.s:788\nruntime.asmcgocall\n\t/usr/lib/go-1.16/src/runtime/asm_amd64.s:652\nruntime.cgocall\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:164\ngithub.com/tinyzimmer/go-glib/glib._Cfunc_g_main_loop_run\n\t_cgo_gotypes.go:2819\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run.func1\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).Run\n\t/workspace/pkg/pipeline/pipeline.go:154\ngithub.com/livekit/egress/pkg/service.(*Service).handleEgress.func2\n\t/workspace/pkg/service/service.go:233"}
{"level":"error","ts":1654778518.9665086,"logger":"egress","caller":"service/service.go:298","msg":"egress failed","nodeID":"NE_EgMpXPasfzmW","egressID":"EG_Tse7rFy7EZSY","error":"Connection error","stacktrace":"github.com/livekit/egress/pkg/service.(*Service).sendEgressUpdate\n\t/workspace/pkg/service/service.go:298\ngithub.com/livekit/egress/pkg/service.(*Service).handleEgress\n\t/workspace/pkg/service/service.go:244\ngithub.com/livekit/egress/pkg/service.(*Service).handleRequest\n\t/workspace/pkg/service/service.go:207\ngithub.com/livekit/egress/pkg/service.(*Service).Run\n\t/workspace/pkg/service/service.go:111\nmain.runService\n\t/workspace/cmd/server/service.go:47\nmain.run\n\t/workspace/cmd/server/main.go:63\ngithub.com/urfave/cli/v2.(*App).RunContext\n\t/root/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:322\ngithub.com/urfave/cli/v2.(*App).Run\n\t/root/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:224\nmain.main\n\t/workspace/cmd/server/main.go:44\nruntime.main\n\t/usr/lib/go-1.16/src/runtime/proc.go:225"}
{"level":"error","ts":1654778532.7877293,"logger":"egress","caller":"pipeline/pipeline.go:271","msg":"pipeline frozen","nodeID":"NE_EgMpXPasfzmW","egressID":"EG_Tse7rFy7EZSY","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).SendEOS.func1\n\t/workspace/pkg/pipeline/pipeline.go:271"}
XIO:  fatal IO error 0 (Success) on X server ":1045276462"
      after 44 requests (44 known processed) with 1 events remaining.
+ pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit
W: [pulseaudio] main.c: Running in system mode, but --disallow-module-loading not set.
N: [pulseaudio] main.c: Running in system mode, forcibly disabling SHM mode.
I: [pulseaudio] main.c: Daemon startup successful.
+ exec ./egress

I was trying to stream livekit room, it works when fresh livekit egress is created. Once the stream is closed its not working.

Blank black screen is being streamed. [Audio/Video is not being streamed.]

I am using default livekit template for streaming.

I am facing same issue in both k8s and vm.

+ pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit
W: [pulseaudio] main.c: Running in system mode, but --disallow-module-loading not set.
N: [pulseaudio] main.c: Running in system mode, forcibly disabling SHM mode.
I: [pulseaudio] main.c: Daemon startup successful.
+ exec ./egress
{"level":"info","ts":1654838411.3277984,"logger":"egress","caller":"messaging/bus.go:16","msg":"connecting to redis work queue","nodeID":"NE_DkANTGquwRsV","addr":"192.168.11.233:6379"}
{"level":"info","ts":1654838597.5048645,"logger":"egress","caller":"service/service.go:302","msg":"egress updated","nodeID":"NE_DkANTGquwRsV","egressID":"EG_WacyBF7A2Z4h","status":"EGRESS_ACTIVE"}
{"level":"info","ts":1654838610.8121672,"logger":"egress","caller":"service/service.go:302","msg":"egress updated","nodeID":"NE_DkANTGquwRsV","egressID":"EG_WacyBF7A2Z4h","status":"EGRESS_ENDING"}
{"level":"info","ts":1654838610.882508,"logger":"egress","caller":"service/service.go:300","msg":"egress completed successfully","nodeID":"NE_DkANTGquwRsV","egressID":"EG_WacyBF7A2Z4h"}
{"level":"info","ts":1654838635.3510537,"logger":"egress","caller":"service/service.go:302","msg":"egress updated","nodeID":"NE_DkANTGquwRsV","egressID":"EG_VCaXnMbbkPLk","status":"EGRESS_ENDING"}
{"level":"error","ts":1654838636.080232,"logger":"egress","caller":"pipeline/pipeline.go:404","msg":"failed to parse pipeline error","nodeID":"NE_DkANTGquwRsV","egressID":"EG_VCaXnMbbkPLk","debug":"../gst/rtmp2/gstrtmp2sink.c(1089): error_callback (): /GstPipeline:pipeline/GstBin:output/GstRtmp2Sink:sink_YzpbxswcwRu9","error":"Connection error","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).handleError\n\t/workspace/pkg/pipeline/pipeline.go:404\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).messageWatch\n\t/workspace/pkg/pipeline/pipeline.go:335\ngithub.com/tinyzimmer/go-gst/gst.goBusFunc\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/gst/cgo_exports.go:128\n_cgoexp_cb8cacfb8eb1_goBusFunc\n\t_cgo_gotypes.go:17347\nruntime.cgocallbackg1\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:292\nruntime.cgocallbackg\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:228\nruntime.cgocallback\n\t/usr/lib/go-1.16/src/runtime/asm_amd64.s:788\nruntime.asmcgocall\n\t/usr/lib/go-1.16/src/runtime/asm_amd64.s:652\nruntime.cgocall\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:164\ngithub.com/tinyzimmer/go-glib/glib._Cfunc_g_main_loop_run\n\t_cgo_gotypes.go:2819\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run.func1\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).Run\n\t/workspace/pkg/pipeline/pipeline.go:154\ngithub.com/livekit/egress/pkg/service.(*Service).handleEgress.func2\n\t/workspace/pkg/service/service.go:233"}
{"level":"error","ts":1654838636.1367583,"logger":"egress","caller":"service/service.go:298","msg":"egress failed","nodeID":"NE_DkANTGquwRsV","egressID":"EG_VCaXnMbbkPLk","error":"Connection error","stacktrace":"github.com/livekit/egress/pkg/service.(*Service).sendEgressUpdate\n\t/workspace/pkg/service/service.go:298\ngithub.com/livekit/egress/pkg/service.(*Service).handleEgress\n\t/workspace/pkg/service/service.go:244\ngithub.com/livekit/egress/pkg/service.(*Service).handleRequest\n\t/workspace/pkg/service/service.go:207\ngithub.com/livekit/egress/pkg/service.(*Service).Run\n\t/workspace/pkg/service/service.go:111\nmain.runService\n\t/workspace/cmd/server/service.go:47\nmain.run\n\t/workspace/cmd/server/main.go:63\ngithub.com/urfave/cli/v2.(*App).RunContext\n\t/root/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:322\ngithub.com/urfave/cli/v2.(*App).Run\n\t/root/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:224\nmain.main\n\t/workspace/cmd/server/main.go:44\nruntime.main\n\t/usr/lib/go-1.16/src/runtime/proc.go:225"}
{"level":"error","ts":1654838650.3526146,"logger":"egress","caller":"pipeline/pipeline.go:271","msg":"pipeline frozen","nodeID":"NE_DkANTGquwRsV","egressID":"EG_VCaXnMbbkPLk","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).SendEOS.func1\n\t/workspace/pkg/pipeline/pipeline.go:271"}
XIO:  fatal IO error 0 (Success) on X server ":1386435262"
      after 49 requests (49 known processed) with 1 events remaining.

When stopEgress, report "pipeline frozen"

Describe the Issue
When I use stopEgress api, report "pipeline frozen"

Detail log:

2022-10-15T04:24:03.399356008Z {"level":"debug","ts":1665807843.3717582,"logger":"egress","caller":"service/handler.go:80","msg":"handling request","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","requestID":"RPC_jcUadiSuK4wk"}
2022-10-15T04:24:03.399449155Z {"level":"info","ts":1665807843.3959792,"logger":"egress","caller":"service/handler.go:128","msg":"egress updated","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","status":"EGRESS_ENDING"}
2022-10-15T04:24:03.413872294Z {"level":"debug","ts":1665807843.400598,"logger":"egress","caller":"sdk/appwriter.go:505","msg":"draining","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","trackID":"TR_AMiBfGVtjEppCa","kind":"audio"}
2022-10-15T04:24:03.414205856Z {"level":"debug","ts":1665807843.4014,"logger":"egress","caller":"service/handler.go:146","msg":"request handled","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","requestID":"RPC_jcUadiSuK4wk","senderID":"ND_PUqFna5f"}
2022-10-15T04:24:03.414225330Z {"level":"debug","ts":1665807843.4023511,"logger":"egress","caller":"pipeline/pipeline.go:466","msg":"sending EOS to pipeline","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:03.414238792Z {"level":"debug","ts":1665807843.4024138,"logger":"egress","caller":"sdk/appwriter.go:505","msg":"draining","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","trackID":"TR_VCy8b3Gq2ABk2m","kind":"video"}
2022-10-15T04:24:03.414251863Z {"level":"debug","ts":1665807843.4024372,"logger":"egress","caller":"sdk/appwriter.go:512","msg":"draining show data","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","trackID":"TR_VCy8b3Gq2ABk2m","kind":"video","startTime":1665807749604602990,"endTime":1665807843402394514,"delay":88849}
2022-10-15T04:24:03.414265474Z {"level":"debug","ts":1665807843.4029996,"logger":"egress","caller":"sdk/appwriter.go:505","msg":"draining","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","trackID":"TR_AMfW5HWLm9zU4v","kind":"audio"}
2022-10-15T04:24:03.414278417Z {"level":"debug","ts":1665807843.4030902,"logger":"egress","caller":"sdk/appwriter.go:512","msg":"draining show data","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","trackID":"TR_AMfW5HWLm9zU4v","kind":"audio","startTime":1665807749604602990,"endTime":1665807843402394514,"delay":88849}
2022-10-15T04:24:03.430030514Z {"level":"debug","ts":1665807843.4007235,"logger":"egress","caller":"sdk/appwriter.go:512","msg":"draining show data","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","trackID":"TR_AMiBfGVtjEppCa","kind":"audio","startTime":1665807749648765494,"endTime":0,"delay":364349}
2022-10-15T04:24:03.430122921Z {"level":"debug","ts":1665807843.4256253,"logger":"egress","caller":"service/handler.go:80","msg":"handling request","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","requestID":"RPC_uyz5hswuvGCN"}
2022-10-15T04:24:03.430139606Z {"level":"debug","ts":1665807843.4257643,"logger":"egress","caller":"sdk/appwriter.go:505","msg":"draining","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","trackID":"TR_VCL9qh4k8Z8xFT","kind":"video"}
2022-10-15T04:24:03.430153464Z {"level":"debug","ts":1665807843.4257987,"logger":"egress","caller":"sdk/appwriter.go:512","msg":"draining show data","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","trackID":"TR_VCL9qh4k8Z8xFT","kind":"video","startTime":1665807749648765494,"endTime":0,"delay":364349}
2022-10-15T04:24:03.430167049Z {"level":"info","ts":1665807843.4257927,"logger":"egress","caller":"service/handler.go:128","msg":"egress updated","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","status":"EGRESS_ENDING"}
2022-10-15T04:24:03.430180317Z {"level":"debug","ts":1665807843.4278357,"logger":"egress","caller":"service/handler.go:146","msg":"request handled","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","requestID":"RPC_uyz5hswuvGCN","senderID":"ND_PUqFna5f"}
2022-10-15T04:24:03.430193375Z {"level":"debug","ts":1665807843.4283607,"logger":"egress","caller":"pipeline/pipeline.go:466","msg":"sending EOS to pipeline","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:03.430206351Z {"level":"debug","ts":1665807843.4290228,"logger":"egress","caller":"sdk/input.go:128","msg":"audio writer finished","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:03.491763410Z {"level":"debug","ts":1665807843.487576,"logger":"egress","caller":"sdk/input.go:136","msg":"video writer finished","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:03.635753595Z {"level":"info","ts":1665807843.6327517,"logger":"egress","caller":"[email protected]/signalclient.go:238","msg":"received offer for subscriber","nodeID":"NE_A3TVuVFZVcyL"}
2022-10-15T04:24:03.635842990Z {"level":"debug","ts":1665807843.6340482,"logger":"egress","caller":"sdk/input.go:136","msg":"video writer finished","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:07.546744128Z {"level":"debug","ts":1665807847.5438342,"logger":"egress","caller":"sdk/input.go:128","msg":"audio writer finished","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:31.350248168Z {"level":"info","ts":1665807871.3496008,"logger":"egress","caller":"stats/monitor.go:142","msg":"high cpu load","nodeID":"NE_VLVwpdqrdLXv","load":99.98770491803279}
2022-10-15T04:24:33.405864025Z {"level":"error","ts":1665807873.4037387,"logger":"egress","caller":"pipeline/pipeline.go:468","msg":"pipeline frozen","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).SendEOS.func1.1.1\n\t/workspace/pkg/pipeline/pipeline.go:468"}
2022-10-15T04:24:33.409096432Z {"level":"debug","ts":1665807873.406767,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.416997627Z {"level":"debug","ts":1665807873.416202,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src_0] STREAM-STATUS - Stream status from multiqueue0: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.417144922Z {"level":"debug","ts":1665807873.4166791,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src_1] STREAM-STATUS - Stream status from multiqueue0: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.443106502Z {"level":"error","ts":1665807873.4420493,"logger":"egress","caller":"pipeline/pipeline.go:468","msg":"pipeline frozen","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).SendEOS.func1.1.1\n\t/workspace/pkg/pipeline/pipeline.go:468"}
2022-10-15T04:24:33.448133966Z {"level":"debug","ts":1665807873.4474752,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.452381073Z {"level":"debug","ts":1665807873.45092,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src_0] STREAM-STATUS - Stream status from multiqueue0: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.491883548Z {"level":"debug","ts":1665807873.4892042,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src_1] STREAM-STATUS - Stream status from multiqueue0: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.560884441Z {"level":"debug","ts":1665807873.560232,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":49933333333,"StreamTime":49933333333,"Timestamp":3600049933333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.568358059Z {"level":"debug","ts":1665807873.565523,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50000000000,"StreamTime":50000000000,"Timestamp":3600050000000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.568444758Z {"level":"debug","ts":1665807873.5656924,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50166666666,"StreamTime":50166666666,"Timestamp":3600050166666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.620876896Z {"level":"debug","ts":1665807873.619866,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50100000000,"StreamTime":50100000000,"Timestamp":3600050100000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.620963198Z {"level":"debug","ts":1665807873.620183,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50066666666,"StreamTime":50066666666,"Timestamp":3600050066666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.784010056Z {"level":"debug","ts":1665807873.7816818,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50133333333,"StreamTime":50133333333,"Timestamp":3600050133333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.784099955Z {"level":"debug","ts":1665807873.7818623,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50200000000,"StreamTime":50200000000,"Timestamp":3600050200000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.806776620Z {"level":"debug","ts":1665807873.804248,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32566666666,"StreamTime":32566666666,"Timestamp":3600032566666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.811159911Z {"level":"debug","ts":1665807873.8099113,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50333333333,"StreamTime":50333333333,"Timestamp":3600050333333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.815782233Z {"level":"debug","ts":1665807873.8150344,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32533333333,"StreamTime":32533333333,"Timestamp":3600032533333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.815842058Z {"level":"debug","ts":1665807873.8153234,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32600000000,"StreamTime":32600000000,"Timestamp":3600032600000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.853004411Z {"level":"debug","ts":1665807873.8518572,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32766666666,"StreamTime":32766666666,"Timestamp":3600032766666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:33.986123219Z {"level":"debug","ts":1665807873.9846718,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50266666666,"StreamTime":50266666666,"Timestamp":3600050266666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.998091536Z {"level":"debug","ts":1665807873.9971309,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50233333333,"StreamTime":50233333333,"Timestamp":3600050233333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:33.998187185Z {"level":"debug","ts":1665807873.9975362,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50300000000,"StreamTime":50300000000,"Timestamp":3600050300000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.034946542Z {"level":"debug","ts":1665807874.033164,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50466666666,"StreamTime":50466666666,"Timestamp":3600050466666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.072888417Z {"level":"debug","ts":1665807874.071892,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32700000000,"StreamTime":32700000000,"Timestamp":3600032700000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.072988191Z {"level":"debug","ts":1665807874.072209,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32666666666,"StreamTime":32666666666,"Timestamp":3600032666666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.077373543Z {"level":"debug","ts":1665807874.0751317,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32733333333,"StreamTime":32733333333,"Timestamp":3600032733333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.097923032Z {"level":"debug","ts":1665807874.0970166,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50400000000,"StreamTime":50400000000,"Timestamp":3600050400000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.105720890Z {"level":"debug","ts":1665807874.1052663,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50366666666,"StreamTime":50366666666,"Timestamp":3600050366666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.109517725Z {"level":"debug","ts":1665807874.1093113,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50433333333,"StreamTime":50433333333,"Timestamp":3600050433333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.109764966Z {"level":"debug","ts":1665807874.1094456,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50600000000,"StreamTime":50600000000,"Timestamp":3600050600000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.146298641Z {"level":"debug","ts":1665807874.1447618,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32900000000,"StreamTime":32900000000,"Timestamp":3600032900000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.155979171Z {"level":"debug","ts":1665807874.154044,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32833333333,"StreamTime":32833333333,"Timestamp":3600032833333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.166901372Z {"level":"debug","ts":1665807874.166427,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32800000000,"StreamTime":32800000000,"Timestamp":3600032800000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.295688918Z {"level":"debug","ts":1665807874.2594798,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50533333333,"StreamTime":50533333333,"Timestamp":3600050533333333,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.295783089Z {"level":"debug","ts":1665807874.259829,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32866666666,"StreamTime":32866666666,"Timestamp":3600032866666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.298753076Z {"level":"debug","ts":1665807874.2959285,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50500000000,"StreamTime":50500000000,"Timestamp":3600050500000000,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.319720488Z {"level":"debug","ts":1665807874.3186996,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":50566666666,"StreamTime":50566666666,"Timestamp":3600050566666666,"Duration":-1}","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.432744900Z {"level":"debug","ts":1665807874.4314778,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from queue0: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.433712673Z {"level":"debug","ts":1665807874.4325073,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from queue1: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.434009097Z {"level":"debug","ts":1665807874.4337912,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from audioAppSrc: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.444858700Z {"level":"debug","ts":1665807874.4438663,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from videoAppSrc: A thread has left its loop function","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.459876056Z {"level":"debug","ts":1665807874.4594486,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33033333333,"StreamTime":33033333333,"Timestamp":3600033033333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.489996444Z {"level":"debug","ts":1665807874.488885,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32966666666,"StreamTime":32966666666,"Timestamp":3600032966666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.496394738Z {"level":"debug","ts":1665807874.495987,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":32933333333,"StreamTime":32933333333,"Timestamp":3600032933333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.496567088Z {"level":"debug","ts":1665807874.4961376,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33000000000,"StreamTime":33000000000,"Timestamp":3600033000000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.496804051Z {"level":"debug","ts":1665807874.4962206,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33166666666,"StreamTime":33166666666,"Timestamp":3600033166666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.538848752Z {"level":"debug","ts":1665807874.5381598,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33100000000,"StreamTime":33100000000,"Timestamp":3600033100000000,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.541390307Z {"level":"debug","ts":1665807874.5410333,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33066666666,"StreamTime":33066666666,"Timestamp":3600033066666666,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.541437253Z {"level":"debug","ts":1665807874.541136,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[x264enc0] QOS - {"Live":false,"RunningTime":33133333333,"StreamTime":33133333333,"Timestamp":3600033133333333,"Duration":-1}","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.629027221Z {"level":"debug","ts":1665807874.6285198,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from queue0: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.629675339Z {"level":"debug","ts":1665807874.6289916,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from queue1: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.629733903Z {"level":"debug","ts":1665807874.6292062,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from audioAppSrc: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.637485866Z {"level":"debug","ts":1665807874.6372833,"logger":"egress","caller":"pipeline/pipeline.go:363","msg":"[src] STREAM-STATUS - Stream status from videoAppSrc: A thread has left its loop function","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.660485410Z {"level":"debug","ts":1665807874.6601262,"logger":"egress","caller":"pipeline/pipeline.go:599","msg":"pipeline stopped","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.704647685Z {"level":"info","ts":1665807874.6715665,"logger":"egress","caller":"service/handler.go:124","msg":"egress failed","nodeID":"NE_A3TVuVFZVcyL","egressID":"EG_MBUx8GYMYqit","error":"pipeline frozen"}
2022-10-15T04:24:34.750801087Z {"level":"debug","ts":1665807874.7503872,"logger":"egress","caller":"service/service.go:267","msg":"deleting handler temporary directory","nodeID":"NE_VLVwpdqrdLXv","path":"/tmp/lkegress/EG_MBUx8GYMYqit"}
2022-10-15T04:24:34.867796916Z {"level":"debug","ts":1665807874.8674388,"logger":"egress","caller":"pipeline/pipeline.go:599","msg":"pipeline stopped","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf"}
2022-10-15T04:24:34.869575144Z {"level":"info","ts":1665807874.868991,"logger":"egress","caller":"service/handler.go:124","msg":"egress failed","nodeID":"NE_kPvongLFqpfC","egressID":"EG_geSxWWZeJksf","error":"pipeline frozen"}
2022-10-15T04:24:34.924819859Z {"level":"debug","ts":1665807874.923875,"logger":"egress","caller":"service/service.go:267","msg":"deleting handler temporary directory","nodeID":"NE_VLVwpdqrdLXv","path":"/tmp/lkegress/EG_geSxWWZeJksf"}

Server
Version: docker, livekit/livekit-server:v1.2.3
Version: docker, livekit/livekit-egress:v1.4.4

Compile Chromium with H.264 support for arm64

When Egress is ran on arm64, we use have a version of Chromium that doesn't support decoding H.264. This means room composite would not render any H.264 encoded videos.

Note: this only happens when one runs Egress on arm64. On amd64, we use Chrome by default, which supports H.264 decoding out of the box.

Egress hidden participant sometimes appears in LiveKitRoom component

Describe the bug
We are using the react components and some egresses in the backend. Some times (let’s say 1/3 times), we have the egress showing up in the react LiveKitRoom component with name like EG_xxxxx. This seems to happen often when an ingress (ogg/ivf via livekit-cli) leaves the call.

Server

  • Version: see below
  • Environment: Kubernetes/RKE2

livekit/egress:v1.5.1
livekit/livekit-server:v1.3.1
livekit/livekit-cli:v1.2

Client

  • SDK: js
  • Version: see below

"@livekit/react-components”: “^1.0.3"
“livekit-client”: “^1.5.0"
“livekit-server-sdk”: “^1.1.0".

To Reproduce
Not always happening, but often in this scenario:

  1. web client (only 1) connect the room
  2. start egress
  3. start ingress
  4. ingress stops
  5. EG_xxxx shows up

Expected behavior
No egress participant visible.

Screenshots
SCR-20221115-p46

Additional context
https://livekit-users.slack.com/archives/C01KVTJH6BX/p1668580708737279

Use URL-friendly file timestamp by default

The default timestamp template function leads to generated filenames like test-room3-2022-10-31 20:04:58.69229565 +0000 UTC m=+0.143102843_00000.ts

the + symbol is not URL friendly. by default it should be using second precision timestamps such as 2022-10-31 20:04:58

Support GPU encode

Gstreamer has built-in support for various GPU accelerated encoders. There could be multiple gstreamer pipelines pre-defined in the egress code(x264enc, nvh264enc, openh264enc, vp8enc, ...) and then selected using the egress configuration/ selected by auto-detecting the hardware. This would be very useful, a single machine could handle much more egress load and reduce operational costs.

StartedAt on egressInfo appears not to be accurate

Firstly, Great project!

I'm planning to run some tests on this, but can I just sense check.

I am seeing incorrect StartedAt on egressInfo data via Webhook events.

I may be missing something – a quick look at the repo and it appears that the StartedAt is generated before the recording has started?

p.Info.StartedAt = time.Now().UnixNano()

Thanks

Error with track composite using HLS segments

The egress service works fine on individual tracks and track composite when generating an MP4. Both upload fine to S3 after completion. When attempting to use HLS I get an error below. Wondering if anyone had any insight. Thanks.

{"level":"error","ts":1659482383.8220048,"logger":"egress","caller":"pipeline/pipeline.go:725","msg":"pipeline error","nodeID":"NE_PDiGa63Zs5mz","egressID":"EG_Zy5A33BurgpG","debug":"../libs/gst/base/gstbasesrc.c(3127): gst_base_src_loop (): /GstPipeline:pipeline/GstBin:input/GstAppSrc:videoAppSrc:\nstreaming stopped, reason not-linked (-1)","message":"Internal data stream error.","error":"Internal data stream error.","stacktrace":"github.com/livekit/egress/pkg/pipeline.(*Pipeline).handleError\n\t/workspace/pkg/pipeline/pipeline.go:725\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).messageWatch\n\t/workspace/pkg/pipeline/pipeline.go:566\ngithub.com/tinyzimmer/go-gst/gst.goBusFunc\n\t/root/go/pkg/mod/github.com/livekit/[email protected]/gst/cgo_exports.go:128\n_cgoexp_752bbda710ba_goBusFunc\n\t_cgo_gotypes.go:17360\nruntime.cgocallbackg1\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:292\nruntime.cgocallbackg\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:228\nruntime.cgocallback\n\t/usr/lib/go-1.16/src/runtime/asm_arm64.s:1055\nruntime.asmcgocall\n\t/usr/lib/go-1.16/src/runtime/asm_arm64.s:917\nruntime.cgocall\n\t/usr/lib/go-1.16/src/runtime/cgocall.go:164\ngithub.com/tinyzimmer/go-glib/glib._Cfunc_g_main_loop_run\n\t_cgo_gotypes.go:2819\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run.func1\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/tinyzimmer/go-glib/glib.(*MainLoop).Run\n\t/root/go/pkg/mod/github.com/tinyzimmer/[email protected]/glib/gmainloop.go:53\ngithub.com/livekit/egress/pkg/pipeline.(*Pipeline).Run\n\t/workspace/pkg/pipeline/pipeline.go:210\ngithub.com/livekit/egress/pkg/service.(*Handler).HandleRequest.func2\n\t/workspace/pkg/service/handler.go:59"}

Buffer too small

For some tracks, the egress recording stops almost immediately after it starts with the error: {"logger":"egress","caller":"source/appwriter.go:181","msg":"could not read packet","egressID":"EG_JWbiQTnRuBaa","trackID":"TR_VS2deqoQWnD23f","kind":"video","error":"buffer too small","stacktrace":"[github.com/livekit/egress/pkg/pipeline/source.(*appWriter).start](http://github.com/livekit/egress/pkg/pipeline/source.(*appWriter).start)\n\t/workspace/pkg/pipeline/source/appwriter.go:181"}

When the file is generated locally after recording the room, there is only audio but no video

Can anyone help me about it?The recording MP4 file has only audio but no video.

  1. I made sure the client called correctly
    // Turns camera track on
    room.localParticipant.setCameraEnabled(true)

    // Turns microphone track on
    room.localParticipant.setMicrophoneEnabled(true)

  2. My Java recording code

             EgressServiceClient client = EgressServiceClient.create(
                     egressHost,
                     appkey,
                     secret
             );
    
             LivekitEgress.EncodedFileOutput output = LivekitEgress.EncodedFileOutput.newBuilder()
                     .setFileType(LivekitEgress.EncodedFileType.MP4)
                     .setFilepath(dir + startUserId + "_" + avType + "_" + roomName + "_" + recordId + ".mp4")
                     .build();
    
             Call<LivekitEgress.EgressInfo> call = client.startRoomCompositeEgress(
                     roomName,
                     output
             );
    
  3. Below is my egress recording log

{"level":"debug","ts":1670900553.9964244,"logger":"egress","caller":"service/service.go:94","msg":"service ready","nodeID":"NE_wnnE2mWnKo5V"}
{"level":"debug","ts":1670900610.4637547,"logger":"egress","caller":"service/service.go:168","msg":"request received","nodeID":"NE_wnnE2mWnKo5V","egressID":"EG_4B4x29RanuoX","requestID":"RPC_bswjuj4HPGCc","senderID":"ND_Afu4bA4r"}
{"level":"debug","ts":1670900610.4647985,"logger":"egress","caller":"stats/monitor.go:157","msg":"cpu request","nodeID":"NE_wnnE2mWnKo5V","accepted":true,"availableCPUs":7.999228536188582,"numCPUs":8}
{"level":"info","ts":1670900610.4663486,"logger":"egress","caller":"service/service.go:211","msg":"request accepted","nodeID":"NE_wnnE2mWnKo5V","egressID":"EG_4B4x29RanuoX","requestID":"RPC_bswjuj4HPGCc","senderID":"ND_Afu4bA4r"}
{"level":"debug","ts":1670900610.46742,"logger":"egress","caller":"params/params.go:724","msg":"writing to file","nodeID":"NE_wnnE2mWnKo5V","egressID":"EG_4B4x29RanuoX","filename":"/out/360435407058862080_0_bjmuhau1670900609595_390458706441986048.mp4"}
{"level":"debug","ts":1670900610.6196644,"logger":"egress","caller":"server/main.go:120","msg":"handler launched","nodeID":"NE_bb7jNsTptzRM"}
{"level":"info","ts":1670900610.6200533,"logger":"egress","caller":"server/main.go:124","msg":"setting TMPDIR environment and creating path","nodeID":"NE_bb7jNsTptzRM","path":"/tmp/lkegress/EG_4B4x29RanuoX"}
{"level":"info","ts":1670900610.6207635,"logger":"egress","caller":"redis/redis.go:63","msg":"connecting to redis","nodeID":"NE_bb7jNsTptzRM","simple":true,"addr":"192.168.2.42:6000"}
{"level":"debug","ts":1670900610.6291676,"logger":"egress","caller":"params/params.go:724","msg":"writing to file","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","filename":"/out/360435407058862080_0_bjmuhau1670900609595_390458706441986048.mp4"}
{"level":"debug","ts":1670900610.6703675,"logger":"egress","caller":"web/source.go:49","msg":"launching xvfb","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","display":":1369852416","dims":"1920x1080x24"}
{"level":"debug","ts":1670900610.6785457,"logger":"egress","caller":"web/source.go:83","msg":"launching chrome","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","url":"https://egress-composite.livekit.io?layout=&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzA5ODcwMTAsImlzcyI6IkFQSXJoOVRRdHUzOVh6WSIsIm5iZiI6MTY3MDkwMDYxMCwic3ViIjoiRUdfNEI0eDI5UmFudW9YIiwidmlkZW8iOnsiY2FuUHVibGlzaCI6ZmFsc2UsImNhblB1Ymxpc2hEYXRhIjpmYWxzZSwiY2FuU3Vic2NyaWJlIjp0cnVlLCJoaWRkZW4iOnRydWUsInJlY29yZGVyIjp0cnVlLCJyb29tIjoiYmptdWhhdTE2NzA5MDA2MDk1OTUiLCJyb29tSm9pbiI6dHJ1ZX19.y0sCt0T3Bzgp7lKss9ronT8qaPWJI6-M-Z2spDvslPQ&url=ws%3A%2F%2F192.168.2.42%3A7880"}
{"level":"debug","ts":1670900621.745696,"logger":"egress","caller":"web/source.go:172","msg":"chrome log: START_RECORDING","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8574605,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8579814,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src_0] STREAM-STATUS - Stream status from multiqueue0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.858149,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src_1] STREAM-STATUS - Stream status from multiqueue0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8586535,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8588307,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src_1] STREAM-STATUS - Stream status from multiqueue0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8590114,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src_0] STREAM-STATUS - Stream status from multiqueue0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8593173,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from queue0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8595412,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from queue0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.859685,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from pulsesrc0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8598511,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from queue1: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8600833,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from ximagesrc0: A new thread needs to be created","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8603354,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from pulsesrc0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.860591,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from ximagesrc0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8607256,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[src] STREAM-STATUS - Stream status from queue1: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8608413,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pipeline] NEW-CLOCK - Got a new clock","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.87325,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[audiosrcringbuffer0] STREAM-STATUS - Stream status from pulsesrc0: A thread has entered its loop function","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.8734393,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] LATENCY - Element's latency has changed","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900621.9074419,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[x264enc0] LATENCY - Element's latency has changed","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900624.4792428,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pipeline] STREAM-START - Pipeline stream is starting","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900624.4803264,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pipeline] ASYNC-DONE - Async task completed","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900624.4804804,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[filesink0] LATENCY - Element's latency has changed","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"info","ts":1670900624.482347,"logger":"egress","caller":"service/handler.go:137","msg":"egress updated","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","request_type":"room_composite","output_type":"file","status":"EGRESS_ACTIVE"}
{"level":"debug","ts":1670900913.8378255,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900914.1063094,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900914.3714826,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900932.0608213,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900932.5125499,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900932.9054615,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900933.179299,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900933.4126434,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670900933.738622,"logger":"egress","caller":"pipeline/pipeline.go:367","msg":"[pulsesrc0] WARNING - Can't record audio fast enough","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670901042.2396193,"logger":"egress","caller":"web/source.go:172","msg":"chrome log: END_RECORDING","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"info","ts":1670901042.242607,"logger":"egress","caller":"service/handler.go:137","msg":"egress updated","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","request_type":"room_composite","output_type":"file","status":"EGRESS_ENDING"}
{"level":"debug","ts":1670901042.24938,"logger":"egress","caller":"pipeline/pipeline.go:462","msg":"sending EOS to pipeline","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670901045.5637372,"logger":"egress","caller":"pipeline/pipeline.go:283","msg":"EOS received, stopping pipeline","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"debug","ts":1670901046.4625423,"logger":"egress","caller":"pipeline/pipeline.go:609","msg":"pipeline stopped","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX"}
{"level":"info","ts":1670901046.7102478,"logger":"egress","caller":"service/handler.go:131","msg":"egress completed","nodeID":"NE_bb7jNsTptzRM","egressID":"EG_4B4x29RanuoX","request_type":"room_composite","output_type":"file"}
{"level":"debug","ts":1670901046.7620223,"logger":"egress","caller":"service/service.go:270","msg":"deleting handler temporary directory","nodeID":"NE_wnnE2mWnKo5V","path":"/tmp/lkegress/EG_4B4x29RanuoX"}

Do not set metadata and tagging unless explicitly defined

#154 broke Digital Ocean spaces support since it doesn't support Tagging.

We should set these fields only when explicitly set by the user

{"level":"error","ts":1667131595.05049,"logger":"egress","caller":"pipeline/pipeline.go:654","msg":"could not upload file","nodeID":"NE_cX5epybD5hGE","egressID":"EG_8KS2fSFZtGDD","location":"S3","error":"InvalidArgument: \n\tstatus code: 400, request id: tx00000000000000f0f0477-00635e68cb-2914aa01-ams3c, host id: ","stacktrace":"[github.com/livekit/egress/pkg/pipeline.(*Pipeline).storeFile](http://github.com/livekit/egress/pkg/pipeline.(*Pipeline).storeFile)

could not launch handler ... invalid argument

I try to make a recording.

Here is my request sending code:

func (rh *RecordHandler) StartRecording(c echo.Context) error {
	chatId, err := utils.ParseInt64(c.Param("id"))
	if err != nil {
		return err
	}
	roomName := fmt.Sprintf("chat%v", chatId)
	filePath := fmt.Sprintf("/files/chat/%v/recording_%v.mp4", chatId, time.Now().Unix())
	streamRequest := &livekit.RoomCompositeEgressRequest{
		RoomName: roomName,
		Layout:   "speaker-dark",
		Output: &livekit.RoomCompositeEgressRequest_File{
			File: &livekit.EncodedFileOutput{
				FileType: livekit.EncodedFileType_MP4,
				Filepath: filePath,
				Output:   new(livekit.EncodedFileOutput_S3),
			},
		},
		AudioOnly: false,
		VideoOnly: false,
		Options: &livekit.RoomCompositeEgressRequest_Preset{
			Preset: livekit.EncodingOptionsPreset_H264_720P_30,
		},
	}
	info, err := rh.egressClient.StartRoomCompositeEgress(c.Request().Context(), streamRequest)

In docker logs of egress I have the following error

{"level":"info","ts":1664572948.0801027,"logger":"egress","caller":"service/service.go:207","msg":"request accepted","nodeID":"NE_HXnBNfBB3Xph","egressID":"EG_xAfYHCePHqma","requestID":"RPC_B7WjTyWZQNuC","senderID":"ND_FgbIM7iG"}
{"level":"error","ts":1664572948.0807633,"logger":"egress","caller":"service/service.go:271","msg":"could not launch handler","nodeID":"NE_HXnBNfBB3Xph","error":"fork/exec /usr/bin/egress: invalid argument","stacktrace":"github.com/livekit/egress/pkg/service.(*Service).launchHandler\n\t/workspace/pkg/service/service.go:271\ngithub.com/livekit/egress/pkg/service.(*Service).Run.func3\n\t/workspace/pkg/service/service.go:127"}
{"level":"info","ts":1664572948.080809,"logger":"egress","caller":"service/service.go:265","msg":"deleting handler temporary directory","nodeID":"NE_HXnBNfBB3Xph","path":"/tmp/lkegress/EG_xAfYHCePHqma"}

For reproducing:
1.

git clone [email protected]:nkonev/videochat.git
cd videochat
git checkout egress
docker-compose up -d
cd frontend
npm i
npm run dev

Start aaa, chat, video in IntelliJ IDEA
In browser http://localhost:8081
admin/admin
Create chat and start a video call

  1. Here is egress
    https://github.com/nkonev/videochat/blob/9f1d588cda26f36cb376503b2eb55518be8407c4/docker-compose.yml#L123

  2. Here is code
    https://github.com/nkonev/videochat/blob/9f1d588cda26f36cb376503b2eb55518be8407c4/video/handlers/record.go#L22

  3. Here is curl

curl -i -X PUT 'http://localhost:1237/video/1/record/start'

Use WebM for TrackEgress

Currently we are using IVF format for track egress as it was the simplest container for VP8 content.

However, for end users webm is the more compatible container, with support by media players and Chrome. We should switch to WebM for VP8 TrackEgress.

Support regional egress selection

Since LiveKit servers can run in a multi-region cluster configuration, it is pretty important that egress selection also be able to take region into account. This would be especially important on many cloud providers that have cheaper/free traffic when communicating between servers within the same region.

I think the same distanceBetween logic from the livekit server region selection should work great for this.

Gstreamer negotiation error

Another (quite rare) exception we are getting is gstreamer negotation error which ends the egress: {"egress_id":"EG_KPLWjHuGDDu","room_id":"RM_CRLnehFJWyNU","status":3,"started_at":1653393512607933675,"ended_at":1653393691015471236,"error":"GStreamer error: negotiation problem.","Request":{"Track"...

Support for IAM roles to access S3

Hi! Seems that currently it is required to always set an access key and secret to access the S3 bucket to save the files. Ideally, it should be possible to use AWS IAM Roles associated with a ServiceAccount instead, since it is more secure.
I think it would be just a matter of using the Role defined on the environment and avoid setting the static credentials here.

I can go for it when I have some free time, just creating the issue here in case someone wants to go first 😄 Thank you!

FileInfo – StartedAt, EndedAt set but not sent

I've been testing #137 I can see that the FileInfo StartedAt and EndedAt are correctly set on the Egress, but they are not being received in the Webhook events.

Livekit (1.2.4), server-sdk-js (master), Egress (master). I can't see what I am missing?

Support CRF as an encoding parameter

some video codecs supports specifying a CRF instead of bitrate, to produce video at a consistent quality (but variable bitrate). we should support this option in the advanced encoding options

Quick correction to deployment documentation

docker run --rm \
    -e EGRESS_CONFIG_FILE=/out/config.yaml \
    -v ~/livekit-egress:/out \
    livekit-egress

should be:

docker run --rm \
    -e EGRESS_CONFIG_FILE=/out/config.yaml \
    -v ~/livekit-egress:/out \
    livekit/egress

for Running Locally section.

Audio drop-outs since recent updates

Following on from ... #142

The silence changes appear to have solved that issue, but I am now getting drop-outs in the audio (for audio only files).

I can supply files if required, but I am able to re-create on every recording.

websocket: close 1006 (abnormal closure): unexpected EOF

Thanks again for the hard work here. I've deployed livekit and livekit egress on AWS EKS using helm. I'm recording MP4 and uploading to S3. Everything seems to be working well except when I stop the recording using stopEgress(), "websocket: close 1006 (abnormal closure): unexpected EOF" is logged and then it takes several minutes for the recording to show up in S3.

Previously the recording was uploaded right after we disconnected from livekit. At that time we had not implemented stopEgress(). We get the same error with disconnect except for one out of around 20 tests. That one time there was no error and it uploaded right away.

We had made some changes to the firewall as well as replaced some of the clusters when the error started. Since then, I've updated to the latest livekit server, egress, and client and server JS APIs but the scenario persists. I've reviewed the documentation and firewall settings but am unable to find the issue. I'm presuming it's something I did with our configuration but cannot find it. Our firewall rules match the documentation and the connection tester is all green without any warnings. The recordings look good once they reach S3 and are high quality, and the system is stable. We could use it as is but I'm presuming the error isn't optimal and it's nearly a requirement for us for the recordings to be available sooner.

I'm not seeing anything of concern on the livekit server. Here is the full log from egress:

{"level":"debug","ts":1662672671.2679987,"logger":"egress","caller":"service/handler.go:81","msg":"handling request","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","requestID":"RPC_UZU79tyCFQQ7"}
{"level":"info","ts":1662672671.2680428,"logger":"egress","caller":"service/handler.go:129","msg":"egress updated","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","status":"EGRESS_ENDING"}
{"level":"debug","ts":1662672671.268796,"logger":"egress","caller":"service/handler.go:147","msg":"request handled","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","requestID":"RPC_UZU79tyCFQQ7","senderID":"ND_XjdjZkw9"}
{"level":"debug","ts":1662672671.2688847,"logger":"egress","caller":"pipeline/pipeline.go:451","msg":"sending EOS to pipeline","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7"}
{"level":"debug","ts":1662672671.2689269,"logger":"egress","caller":"source/appwriter.go:507","msg":"draining","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","trackID":"TR_VCJ4H38uFva7Wp","kind":"video"}
{"level":"debug","ts":1662672671.2689493,"logger":"egress","caller":"source/appwriter.go:507","msg":"draining","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","trackID":"TR_AMURL74WvcV3i2","kind":"audio"}
{"level":"debug","ts":1662672671.486058,"logger":"egress","caller":"pipeline/pipeline.go:268","msg":"EOS received, stopping pipeline","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7"}
{"level":"debug","ts":1662672671.488385,"logger":"egress","caller":"pipeline/pipeline.go:579","msg":"pipeline stopped","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7"}

Error:
{"level":"error","ts":1662672671.4932966,"logger":"egress","caller":"runtime/asm_amd64.s:1571","msg":"error with read worker","nodeID":"NE_Mk9becqXtdx3","error":"websocket: close 1006 (abnormal closure): unexpected EOF","stacktrace":"runtime.goexit\n\t/usr/lib/go-1.18/src/runtime/asm_amd64.s:1571"}

Then 258 seconds later:
{"level":"debug","ts":1662672929.3446214,"logger":"egress","caller":"pipeline/pipeline.go:606","msg":"uploading to s3","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7"}
{"level":"debug","ts":1662672929.4825525,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"removing temporary directory","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7","path":"/EG_px2xQzW8J7r7/"}
{"level":"info","ts":1662672929.48277,"logger":"egress","caller":"service/handler.go:127","msg":"egress completed","nodeID":"NE_Mk9becqXtdx3","egressID":"EG_px2xQzW8J7r7"}
{"level":"info","ts":1662672929.4856944,"logger":"egress","caller":"service/service.go:265","msg":"deleting handler temporary directory","nodeID":"NE_t2FZZB73NKJf","path":"/tmp/lkegress/EG_px2xQzW8J7r7"}

Invalid Track Composite archive when the participant publishes new tracks

Hi !

The blog post about Egress launch reads the following:
https://blog.livekit.io/livekit-universal-egress-launch/

Track Composite automatically synchronizes and combines a single participant's audio and video tracks, and exports them to a standalone file or RTMP stream. This option is handy for recording each participant individually, such as during a live performance.

However, we made some tests, and it seems that in track composite mode, if the participant publishes a new track, the track is not added to the output video archive. For instance, if a participant has an audio track published, starts egress track composite, and then publishes a video track, the resulting archive will only contain the audio stream.

Is it the expected behavior ? In this case, should I start a new track composite egress whenever a new track is published within the participant's stream ? More generally, how to deal with change of camera or microphone ?

Thanks a lot 🙏

Consider use Argo Workflow Engine to spawn pod

By using Argo Workflow Engine, we can https://argoproj.github.io/workflows/

  1. Easy to scale up for transcode by spawn pod dynamically
  2. Allocate and limited CPU to ensure each pod will not affect the other also spot instance for cost saving https://argoproj.github.io/argo-workflows/cost-optimisation/
  3. Factorize existing workflow into multiple step to introduce re-try (Such as if push egress file to public cloud fail, the file will be lost forever with current implementation https://argoproj.github.io/argo-workflows/retries/

Recording failed

describe:The live broadcast is normal, the recording of the live broadcast is unsuccessful, and the stream is pushed to the srs server through rtmp, and then the pull stream also fails. all black

Pictures from the live broadcast

image

Recording failed

failed to access template

http://egress-composite.livekit.io/?layout=speaker-dark&url=ws%3A%2F%2F192.168.65.2%3A7880&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTY2Njc2MTYsImlzcyI6IkFQSVBqeFk3bmNjWnpFbyIsIm5iZiI6MTY1NjU4MTIxNiwic3ViIjoiRUdfN2JtcUFtaDRyd0NmIiwidmlkZW8iOnsiY2FuUHVibGlzaCI6ZmFsc2UsImNhblB1Ymxpc2hEYXRhIjpmYWxzZSwiY2FuU3Vic2NyaWJlIjp0cnVlLCJoaWRkZW4iOnRydWUsInJlY29yZGVyIjp0cnVlLCJyb29tIjoidGVzdDU1NTU1Iiwicm9vbUpvaW4iOnRydWV9fQ.QJq8DGj1EuspVkOC2l5Z_R1vyrhb4vF5XGPkK-K9UdM

image

The resulting recorded live video is a black screen

image

Why is there no audio and video recorded?

livekit-serve log

2022-06-30T09:23:45.782Z	INFO	livekit	service/wire_gen.go:168	using multi-node routing via redis	{"sentinel": false, "addr": "redis:6379"}
2022-06-30T09:23:45.869Z	INFO	livekit	service/server.go:197	starting LiveKit server	{"addr": ":7880", "nodeID": "ND_198vKAkb", "nodeIP": "192.168.1.89", "version": "1.1.0", "rtc.portTCP": 7881, "rtc.portUDP": 7882}
2022-06-30T09:26:13.826Z	INFO	livekit	service/rtcservice.go:211	new client WS connected	{"room": "test55555", "participant": "kkk", "connID": "CO_K5rPBGek3GSD", "roomID": "RM_UcB9Z8T3HLUx"}
2022-06-30T09:26:13.839Z	INFO	livekit	rtc/room.go:276	new participant joined	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "pID": "PA_KzcBVYzNCB65", "participant": "kkk", "protocol": 7, "options": {"AutoSubscribe":true}}
2022-06-30T09:26:14.575Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "audio", "trackID": "TR_AMy9nDFrSrwmvQ", "rid": "", "SSRC": 449006131}
2022-06-30T09:26:14.985Z	INFO	livekit	buffer/buffer.go:187	REMB not supported, RTCP feedback will not be generated	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "trackID": "TR_VCVJYtHm7zXuQ9", "mime": "video/vp8", "layer": 0}
2022-06-30T09:26:14.986Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "video", "trackID": "TR_VCVJYtHm7zXuQ9", "rid": "q", "SSRC": 2432298574}
2022-06-30T09:26:14.991Z	INFO	livekit	buffer/buffer.go:187	REMB not supported, RTCP feedback will not be generated	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "trackID": "TR_VCVJYtHm7zXuQ9", "mime": "video/vp8", "layer": 1}
2022-06-30T09:26:14.991Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "video", "trackID": "TR_VCVJYtHm7zXuQ9", "rid": "h", "SSRC": 1195882202}
2022-06-30T09:26:15.259Z	INFO	livekit	buffer/buffer.go:187	REMB not supported, RTCP feedback will not be generated	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "trackID": "TR_VCVJYtHm7zXuQ9", "mime": "video/vp8", "layer": 2}
2022-06-30T09:26:15.259Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "video", "trackID": "TR_VCVJYtHm7zXuQ9", "rid": "f", "SSRC": 1281133605}
2022-06-30T09:30:19.776Z	INFO	livekit	buffer/buffer.go:187	REMB not supported, RTCP feedback will not be generated	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "trackID": "TR_VShXseUVXrvSCg", "mime": "video/vp8", "layer": 0}
2022-06-30T09:30:19.779Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "video", "trackID": "TR_VShXseUVXrvSCg", "rid": "q", "SSRC": 30706227}
2022-06-30T09:30:19.804Z	INFO	livekit	buffer/buffer.go:187	REMB not supported, RTCP feedback will not be generated	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "trackID": "TR_VShXseUVXrvSCg", "mime": "video/vp8", "layer": 1}
2022-06-30T09:30:19.804Z	INFO	livekit	rtc/participant.go:1104	mediaTrack published	{"room": "test55555", "roomID": "RM_UcB9Z8T3HLUx", "participant": "kkk", "pID": "PA_KzcBVYzNCB65", "kind": "video", "trackID": "TR_VShXseUVXrvSCg", "rid": "h", "SSRC": 3593677690}

egress log

+ pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit
W: [pulseaudio] main.c: Running in system mode, but --disallow-module-loading not set.
N: [pulseaudio] main.c: Running in system mode, forcibly disabling SHM mode.
I: [pulseaudio] main.c: Daemon startup successful.
+ exec egress
{"level":"info","ts":1656581025.7347176,"logger":"egress","caller":"server/main.go:169","msg":"connecting to redis","nodeID":"NE_ZHF2QFBm6utJ","addr":"redis:6379"}
{"level":"debug","ts":1656581025.7416909,"logger":"egress","caller":"service/service.go:65","msg":"starting service","nodeID":"NE_ZHF2QFBm6utJ"}
{"level":"debug","ts":1656581025.7469819,"logger":"egress","caller":"service/service.go:95","msg":"service ready","nodeID":"NE_ZHF2QFBm6utJ"}
{"level":"debug","ts":1656581216.8710685,"logger":"egress","caller":"service/service.go:161","msg":"request received","nodeID":"NE_ZHF2QFBm6utJ","egressID":"EG_7bmqAmh4rwCf","requestID":"RPC_iEYWtigsfV9C","senderID":"ND_198vKAkb"}
{"level":"debug","ts":1656581216.8711743,"logger":"egress","caller":"sysload/cpu.go:154","msg":"cpu request","nodeID":"NE_ZHF2QFBm6utJ","accepted":true,"availableCPUs":5.8860103626943,"numCPUs":6}
{"level":"info","ts":1656581216.8722072,"logger":"egress","caller":"service/service.go:204","msg":"request accepted","nodeID":"NE_ZHF2QFBm6utJ","egressID":"EG_7bmqAmh4rwCf","requestID":"RPC_iEYWtigsfV9C","senderID":"ND_198vKAkb"}
{"level":"debug","ts":1656581216.872407,"logger":"egress","caller":"params/params.go:591","msg":"writing to file","nodeID":"NE_ZHF2QFBm6utJ","egressID":"EG_7bmqAmh4rwCf","filename":"/EG_7bmqAmh4rwCf/caumoo23k1kc0evptlug.mp4"}
{"level":"debug","ts":1656581216.911763,"logger":"egress","caller":"server/main.go:119","msg":"handler launched","nodeID":"NE_RQnq7gc7hkAD"}
{"level":"info","ts":1656581216.912395,"logger":"egress","caller":"server/main.go:169","msg":"connecting to redis","nodeID":"NE_RQnq7gc7hkAD","addr":"redis:6379"}
{"level":"debug","ts":1656581216.9191887,"logger":"egress","caller":"params/params.go:591","msg":"writing to file","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","filename":"/EG_7bmqAmh4rwCf/caumoo23k1kc0evptlug.mp4"}
{"level":"debug","ts":1656581216.9376624,"logger":"egress","caller":"source/web.go:114","msg":"launching xvfb","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","display":":2125642851","dims":"1920x1080x24"}
{"level":"debug","ts":1656581216.9416354,"logger":"egress","caller":"source/web.go:128","msg":"launching chrome","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","url":"https://egress-composite.livekit.io?layout=speaker-dark&url=ws%3A%2F%2F192.168.65.2%3A7880&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTY2Njc2MTYsImlzcyI6IkFQSVBqeFk3bmNjWnpFbyIsIm5iZiI6MTY1NjU4MTIxNiwic3ViIjoiRUdfN2JtcUFtaDRyd0NmIiwidmlkZW8iOnsiY2FuUHVibGlzaCI6ZmFsc2UsImNhblB1Ymxpc2hEYXRhIjpmYWxzZSwiY2FuU3Vic2NyaWJlIjp0cnVlLCJoaWRkZW4iOnRydWUsInJlY29yZGVyIjp0cnVlLCJyb29tIjoidGVzdDU1NTU1Iiwicm9vbUpvaW4iOnRydWV9fQ.QJq8DGj1EuspVkOC2l5Z_R1vyrhb4vF5XGPkK-K9UdM"}
{"level":"debug","ts":1656581221.595888,"logger":"egress","caller":"source/web.go:212","msg":"chrome log: START_RECORDING","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6350396,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A new thread needs to be created","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6352065,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from queue0: A new thread needs to be created","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6352396,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from mp4mux0: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6352954,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from queue0: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6353571,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from queue1: A new thread needs to be created","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6354356,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from queue1: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.635546,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from ximagesrc0: A new thread needs to be created","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.635617,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from pulsesrc0: A new thread needs to be created","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6356897,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[pipeline] NEW-CLOCK - Got a new clock","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6357462,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from ximagesrc0: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6359053,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[src] STREAM-STATUS - Stream status from pulsesrc0: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.638062,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[audiosrcringbuffer0] STREAM-STATUS - Stream status from pulsesrc0: A thread has entered its loop function","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.638899,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[pulsesrc0] LATENCY - Element's latency has changed","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581221.6448984,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[x264enc0] LATENCY - Element's latency has changed","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581223.7135222,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[pipeline] STREAM-START - Pipeline stream is starting","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581223.7136822,"logger":"egress","caller":"pipeline/pipeline.go:639","msg":"[pipeline] ASYNC-DONE - Async task completed","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"info","ts":1656581223.71529,"logger":"egress","caller":"service/handler.go:129","msg":"egress updated","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","status":"EGRESS_ACTIVE"}
{"level":"debug","ts":1656581289.708992,"logger":"egress","caller":"service/handler.go:81","msg":"handling request","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","requestID":"RPC_hVsiKhqkvFeM"}
{"level":"info","ts":1656581289.7090523,"logger":"egress","caller":"service/handler.go:129","msg":"egress updated","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","status":"EGRESS_ENDING"}
{"level":"debug","ts":1656581289.70937,"logger":"egress","caller":"pipeline/pipeline.go:476","msg":"sending EOS to pipeline","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581289.7114043,"logger":"egress","caller":"service/handler.go:147","msg":"request handled","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","requestID":"RPC_hVsiKhqkvFeM","senderID":"ND_198vKAkb"}
{"level":"debug","ts":1656581289.7149282,"logger":"egress","caller":"pipeline/pipeline.go:560","msg":"EOS received, stopping pipeline","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581289.733569,"logger":"egress","caller":"pipeline/pipeline.go:677","msg":"pipeline stopped","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581289.8023732,"logger":"egress","caller":"pipeline/pipeline.go:291","msg":"uploading to s3","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}
{"level":"debug","ts":1656581290.8030593,"logger":"egress","caller":"pipeline/pipeline.go:258","msg":"removing temporary directory","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf","path":"/EG_7bmqAmh4rwCf/"}
{"level":"info","ts":1656581290.8035176,"logger":"egress","caller":"service/handler.go:127","msg":"egress completed","nodeID":"NE_RQnq7gc7hkAD","egressID":"EG_7bmqAmh4rwCf"}

Redis: channel is full

redis: 2022/05/26 12:33:07 pubsub.go:605: redis: &{%!s(*redis.PubSub=&{0xc00026c0e0 0xa9e120 0xa9ed40 {0 0} 0xc00058a050 map[EG_START:{}] map[] false 0xc00034a300 0xc00068e480 {1 {0 0}} 0xc0005840c0 <nil>}) %!s(chan *redis.Message=0xc00068e240) %!s(chan interface {}=<nil>) %!s(chan struct {}=0xc00004a060) %!s(int=100) %!s(time.Duration=60000000000) %!s(time.Duration=3000000000)} channel is full for 1m0s (message is dropped)

Draining mode not working correctly

We added terminationGracePeriodSeconds to our egress pods. During the recording the pod was in Terminating state but when I stopped the recorder, this happened: the pod was killed but no video uploaded or webhook sent.

Allow use of a filename template to customize the filename / path used for recordings

Rather than having to specify the exact name of the file written by the egress service, it would be nice to be able to provide a handlebars style template that can make use of room and track information within the filename. This could be used for example to make sure that all of the tracks for a room end up in the same folder in the cloud storage bucket or to encode specific metadata about the track in the filename.

MP4 & HLS recording corruption after streamer disconnects

I have issue with LiveKit Cloud.
When a streamer disconnects due to network issue (or other short interrupt) egress still works, but MP4 recording on S3 becomes corrupted after stream is stoped. There is no seamless transition in video and audio, video just stalls.

UPDATE:
it happened only when using TrackCompositeEgressRequest,
RoomCompositeEgressRequest works correctly

&livekit.TrackCompositeEgressRequest{
	RoomName:     "test-room3",
	AudioTrackId: "TR_AMUeuCNthEmzn7",
	VideoTrackId: "TR_VCVRmHNrygNWWK",
	Output: &livekit.TrackCompositeEgressRequest_File{
		File: &livekit.EncodedFileOutput{
			FileType:        livekit.EncodedFileType_MP4,
			Filepath:        "/test",
			DisableManifest: false,
			Output: &livekit.EncodedFileOutput_S3{
				S3: &livekit.S3Upload{
					AccessKey: "xxx",
					Secret:    "xxx",
					Region:    "ams3",
					Endpoint:  "ams3.digitaloceanspaces.com",
					Bucket:    "xxx",
				},
			},
		},
	},

S3 access key and secret

Hi! First let me thank you for the great work on this project 🙇

I've been trying it out and recently deployed successfully both livekit-server and livekit-egress on a kubernetes cluster using the provided helm charts. All good, but I have some questions regarding the access key and secret to be able to upload to the S3 buckets:

  1. First I was trying to use an AWS Role associated with a ServiceAccount to upload to the buckets from egress but then I quickly realised that the access key and secret were the only supported way. Would it be possible to use Role instead? I think it would be just a matter of using the Role defined on the environment and avoid setting the static credentials here right 🤔 ?
  2. Why do we have the set the credentials for S3 both in the client side while calling egress API and also on the egress server side? 😕

Thank you 🙇

track + trackComposite issues (writing audio).

I'm noticing an issue with track and trackComposite.

I'll try and explain – I'm still investigating – (I have files which I can supply).

Example: Audio recording which is 32 seconds where the user spoke through out. Resulting file has the correct duration, but the audio is within the first half of the recording.

I can confirm that if I record the roomComposite (as well) or/and add video to the trackComposite then the audio playback is fine, although additionally I am seeing drift on occasion in this area.

My assumption right now is just how the frames are being written, but I haven't looked deeper at this stage. I wanted to raise this issue first to see if there is any knowledge of this before I look deeper.

Store in local disk

Thanks for the new recording system. Not all the users are using online storage services. How to store files in local disk?

Egress status stay active when participant disconnect

Hey, thanks for the awesome work. We are using LiveKit and it's egress system in production in GCP + k8s. We do live transcription through audio track egress, and we noticed something strange but not impacting regarding egress status. When a participant is leaving, the egress status stay ACTIVE (the result of the command livekit-cli list-egress) but we observe the correspond WebSocket to be close. Should not the status be COMPLETE instead?

We have a bash script to recreate this issue:

egress.sh
#!/usr/bin/env bash

###
# Script to load test livekit egress. It will start as much audio egress as nb_participants.
#
# Execute it like ./livekit-egress-loadtester.sh <livekit_url> <api_key> <api_secret> <nb_participants> <room_duration>
# Ex:
# ./loadtester.sh api_key api_secret 60 10m
#
# Params:
# livekit_url: The url of the livekit instance to be tested
# api_key: Livekit api key
# api_secret: Livekit api secret
# nb_participants: How many participants
# room_duration: How long room will last
###

TEST_ID=$(date -u +"%Y-%m-%dT%H_%M_%SZ")

LIVEKIT_URL=$1
API_KEY=$2
API_SECRET=$3
NB_PARTICIPANTS=${4-4}
TEST_TIME=${5-30s}

roomName="room-egress-test"
logFile="room-egress-test_$TEST_ID.log"

livekit-cli load-test \
  --url "$LIVEKIT_URL" \
  --api-key "$API_KEY" \
  --api-secret "$API_SECRET" \
  --room $roomName \
  --duration "$TEST_TIME" \
  --subscribers 1 \
  --publishers "$NB_PARTICIPANTS" \
  --audio-bitrate 100000 \
   | tee "$logFile" | sed -un "s/^subscribed to track .* \(.*\) audio.*/\1/p" | while read -r id; # Extract audio track ids to start egress
do
  sleep 1 # Avoid starting all egress at the same time, to avoid egress service to refuse to start because too much requests at the same time.
  echo "Starting egress for $id"
  requestFileName="request-$id.json"
  # Edit this line to change target of egress (for instance WS instead of bucket)
  echo "{ \"room_name\": \"$roomName\", \"track_id\": \"$id\", \"file\": { \"filepath\": \"livekit-egress-test/$TEST_ID/$id.ogg\" } }" > "$requestFileName"
  livekit-cli start-track-egress --url "$LIVEKIT_URL" --api-key "$API_KEY" --api-secret "$API_SECRET" --request "$requestFileName" &
done &

echo "egress room started."

loadTestPid=$!
wait $loadTestPid

echo "egress room ended."

By running this script, as many audio egress as participants will be started, and they will store their results on cloud storage. At the end of the test, we can find all the audio files, but if we run livekit-cli list-egress, most of the egress will still be in ACTIVE state.

Is is normal the status of the egress stay ACTIVE even if the corresponding participant leaved the room? Thanks!

Allow full room recording (without composites)

It appears that currently you can request a composite video, a composite audio track, or an individual track to be saved. For many cases like transcription or offline compositing, it is required to be able to save all the tracks as individual streams without compositing. While this could be done via callbacks, I believe the correct way to do it is probably to extend the egress service with an additional type of egress. These scenarios also typically require some track metadata to be written in order to be able to make use of the individual tracks (#118)

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.