gostream

package module
v0.0.0-...-bdbcc17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2021 License: MIT Imports: 32 Imported by: 0

README

MOVED

New project is at trevor403/noLatency


gostream

(Forked from edaniels/gostream)

gostream is a library to simplify the streaming of images as video to a series of WebRTC peers. The impetus for this existing was for doing simple GUI / video streaming to a browser all within go with as little cgo as possible. The package will likely be refactored over time to support some more generalized use cases and as such will be in version 0 for the time being. Many parameters are hard coded and need to be configurable over time. Use at your own risk, and please file issues!

PkgGoDev Go Report Card


TODO

  • Support multiple codes (e.g. Firefox macos-arm does not support h264 by default yet)
  • Address code TODOs (including context.TODO)
  • Documentation (inner func docs, package docs, example docs)
  • Version 0.1.0
  • Tests

Future Work

  • Sound streaming (with video synchronization)

Examples

  • Stream current desktop: go run github.com/trevor403/gostream/cmd/stream_desktop

Notes

Firefox freezing

For some reason unknown yet, Firefox appears to freeze frequently. This is very unlikely an issue with pion/webrtc and very likely an issue with this library based on current testing. Current thoughts are that it has to do with the timing of writes causing dropped/faulty packets from the perspective of Firefox. Chromium seems to work just fine. Running Firefox with --MOZ_LOG=webrtc_trace:5 can show the errors it is seeing. There are a lot of no GoP in frame drops as well as NACK frame drops. Also curious if the issue is made worse with larger frames and different frame formats.

Using mDNS

  • mDNS (.local addresses) don't seem to work well with WebRTC yet. Random STUN/TURN failures appear to occur. At your own risk, you can address this in Firefox in about:config with media.peerconnection.ice.obfuscate_host_addresses set to false and in Chrome with chrome://flags/#enable-webrtc-hide-local-ips-with-mdns set to Disabled.

Building

Prerequisites

  • libvpx

Linux: libvpx-dev

macOS: brew install libvpx

  • x264

Linux: libx264-dev

macOS: brew install x264

Development

Linting

make lint

Testing

make test

Acknowledgements

If I somehow took code from somewhere without acknowledging it here or via the go.mod, please file an issue and let me know.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Debug = false

Debug is helpful to turn on when the library isn't working quite right.

View Source
var (
	// DefaultICEServers is the default set of ICE servers to use for WebRTC session negotiation.
	DefaultICEServers = []webrtc.ICEServer{

		{
			URLs:           []string{"stun:stun.trevor.jp:3478", "turn:turn.trevor.jp:3478?transport=udp"},
			Username:       "trevor",
			Credential:     getenvs.GetEnvString("TURN_PASSWORD", "redacted"),
			CredentialType: webrtc.ICECredentialTypePassword,
		},
	}
)
View Source
var ErrServerAlreadyStarted = errors.New("already started")

ErrServerAlreadyStarted happens when the server has already been started.

View Source
var Logger = golog.Global

Logger is used various parts of the package for informational/debugging purposes.

View Source
var PartialDefaultViewConfig = ViewConfig{
	StreamNumber: 0,
	WebRTCConfig: webrtc.Configuration{
		ICEServers: DefaultICEServers,
	},
}

PartialDefaultViewConfig is invalid by default; it requires an EncoderFactory to be set.

Functions

func LocalIP

func LocalIP() (net.IP, error)

LocalIP get the host machine local IP address

func StreamNamedSource

func StreamNamedSource(ctx context.Context, is ImageSource, name string, view View)

StreamNamedSource streams the given image source to the view forever until context signals cancelation. The given name is used to identify the stream.

func StreamSource

func StreamSource(ctx context.Context, is ImageSource, view View)

StreamSource streams the given image source to the view forever until context signals cancelation.

Types

type AutoTiler

type AutoTiler struct {
	// contains filtered or unexported fields
}

An AutoTiler automatically tiles a series of images from sources. It rudimentarily swaps between veritcal and horizontal splits and makes all images the same size within a grid. This can produce aesthetically unappealing results but it gets the job done in a pinch where you don't want multiple streams. AutoTiler supports adding image sources over time (but not removing them yet).

func NewAutoTiler

func NewAutoTiler(maxWidth, maxHeight int, sources ...ImageSource) *AutoTiler

NewAutoTiler returns an AutoTiler that adapts its image sources to the given width and height.

func NewAutoTilerVertical

func NewAutoTilerVertical(maxWidth, maxHeight int, sources ...ImageSource) *AutoTiler

NewAutoTilerVertical returns an AutoTiler that adapts its image sources to the given width and height. This AutoTiler starts its splits vertically, instead of horizontally.

func (*AutoTiler) AddSource

func (at *AutoTiler) AddSource(src ImageSource)

AddSource adds another image source to the tiler. It will appear down and to the right of the main image.

func (*AutoTiler) Close

func (at *AutoTiler) Close() error

Close closes all underlying image sources.

func (*AutoTiler) Next

func (at *AutoTiler) Next(ctx context.Context) (image.Image, func(), error)

Next produces an image of every source tiled into one main image. If any of the image sources error, the image will not be included in the main image but it can certainly appear in subsequent ones. Images are fetched in parallel with no current constraint on parallelism.

func (*AutoTiler) SetLogger

func (at *AutoTiler) SetLogger(logger golog.Logger)

SetLogger sets an optional logger to use for debug information.

type ClientResponder

type ClientResponder interface {
	Send(data []byte)
	SendText(s string)
}

A ClientResponder is able to respond directly to a client. This is used in the onData/Click handlers.

type FrameReleasePair

type FrameReleasePair struct {
	Frame   image.Image
	Release func()
}

FrameReleasePair associates a frame with a corresponding function to release its resources once the receiver of a pair is finished with the frame.

type ImageSource

type ImageSource interface {
	// Next returns an image along with a function to release
	// the image once it is no longer used. Not calling the function
	// will not leak memory but may cause the implementer to be
	// as efficient with memory.
	Next(ctx context.Context) (image.Image, func(), error)
	Close() error
}

An ImageSource is responsible for producing images when requested. A source should produce the image as quickly as possible and introduce no rate limiting of its own as that is handled internally.

type ImageSourceFunc

type ImageSourceFunc func(ctx context.Context) (image.Image, func(), error)

An ImageSourceFunc is a helper to turn a function into an ImageSource

func (ImageSourceFunc) Close

func (isf ImageSourceFunc) Close() error

Close does nothing.

func (ImageSourceFunc) Next

func (isf ImageSourceFunc) Next(ctx context.Context) (image.Image, func(), error)

Next calls the underlying function to get an image.

type ResizeImageSource

type ResizeImageSource struct {
	Src           ImageSource
	Width, Height int
}

ResizeImageSource resizes images to the set dimensions.

func (ResizeImageSource) Close

func (ris ResizeImageSource) Close() error

Close closes the underlying source.

func (ResizeImageSource) Next

func (ris ResizeImageSource) Next(ctx context.Context) (image.Image, func(), error)

Next returns a resized image to Width x Height dimensions.

type RotateImageSource

type RotateImageSource struct {
	Src         ImageSource
	RotateByDeg float64
}

RotateImageSource rotates images by a set amount of degrees.

func (*RotateImageSource) Close

func (rms *RotateImageSource) Close() error

Close closes the underlying source.

func (*RotateImageSource) Next

func (rms *RotateImageSource) Next(ctx context.Context) (image.Image, func(), error)

Next returns a rotated image by RotateByDeg degrees.

type Stream

type Stream interface {
	InputFrames() chan<- FrameReleasePair
}

A Stream is sink that accepts any image frames for the purpose of displaying in a view.

type View

type View interface {
	// Stop stops further processing of streams and will not accept new
	// connections.
	Stop()
	// Ready signals that there is at least one client connected and that
	// streams are ready for input.
	StreamingReady() <-chan struct{}
	// SetOnSizeHandler sets a handler for clicks on the view. This is typically
	// used to alter the view or send information back with SendDataToAll or SendTextToAll.
	SetOnSizeHandler(func(ctx context.Context, factor float32, responder ClientResponder))
	// SetOnDataHandler sets a handler for data sent to the view. This is typically
	// used to alter the view or send information back with the responder.
	SetOnDataHandler(func(ctx context.Context, data []byte, responder ClientResponder))
	// SendDataToAll allows sending arbitrary data to all clients.
	SendDataToAll(data []byte)
	// SendCursorToAll ...
	SendCursorToAll(img image.Image, width int, height int, hotx int, hoty int)
	// SendTextToAll allows sending arbitrary messages to all clients.
	SendTextToAll(msg string)
	// HTML returns the HTML needed to interact with the view in a browser.
	HTML() ViewHTML
	// SinglePageHTML returns a complete HTML document that can interact with the view in a browser.
	SinglePageHTML() string
	// Handler returns a named http.Handler that handles new WebRTC connections.
	Handler() ViewHandler
	// ReserveStream allocates a Stream of the given name to be able to stream images to. Reserving
	// streams after the Ready signal is fired is currently not allowed but the method will not fail.
	// This is a lower level method and typically StreamSource is used instead.
	ReserveStream(name string) Stream
}

A View represents a view of streams that can be communicated with from a client.

func NewView

func NewView(config ViewConfig) (View, error)

NewView returns a newly configured view that can begin to handle new connections.

type ViewConfig

type ViewConfig struct {
	StreamNumber   int
	StreamName     string
	WebRTCConfig   webrtc.Configuration
	EncoderFactory codec.EncoderFactory
	// TargetFrameRate will hint to the View to try to maintain this frame rate.
	TargetFrameRate int
	Logger          golog.Logger
}

A ViewConfig describes how a View should be managed.

type ViewHTML

type ViewHTML struct {
	JavaScript string
	Body       string
}

ViewHTML is the HTML needed to interact with the view in a browser.

type ViewHandler

type ViewHandler struct {
	Name string
	Func http.HandlerFunc
}

A ViewHandler names a view and its http.Handler for processing new WebRTC connections.

type ViewServer

type ViewServer interface {
	// Start starts the server and waits for new connections.
	Start() error
	// Stop stops the server and stops the underlying views.
	Stop(ctx context.Context) error
}

A ViewServer is a convenience helper for solely streaming a series Views. Views can be added over time for future new connections.

func NewViewServer

func NewViewServer(port int, view View, logger golog.Logger) ViewServer

NewViewServer returns a server that will run on the given port and initially starts with the given view.

Directories

Path Synopsis
cmd
vpx
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL