Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mutablelogic/go-media
go media services
https://github.com/mutablelogic/go-media
chromaprint dvb dvb-t ffmpeg golang media mpeg mpegts raspberrypi
Last synced: 8 days ago
JSON representation
go media services
- Host: GitHub
- URL: https://github.com/mutablelogic/go-media
- Owner: mutablelogic
- License: apache-2.0
- Created: 2018-04-24T18:52:58.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2024-08-16T10:40:16.000Z (4 months ago)
- Last Synced: 2024-11-22T12:51:35.223Z (20 days ago)
- Topics: chromaprint, dvb, dvb-t, ffmpeg, golang, media, mpeg, mpegts, raspberrypi
- Language: Go
- Homepage: https://pkg.go.dev/github.com/mutablelogic/go-media
- Size: 54 MB
- Stars: 30
- Watchers: 2
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-repositories - mutablelogic/go-media - go media services (Go)
README
# go-media
This module provides an interface for media services, including:
* Bindings in golang for [FFmpeg 6.1](https://ffmpeg.org/);
* Opening media files, devices and network sockets for reading and writing;
* Retrieving metadata and artwork from audio and video media;
* Re-multiplexing media files from one format to another;
* Fingerprinting audio files to identify music.## Current Status
This module is currently in development and subject to change. If there are any specific features
you are interested in, please see below "Contributing & Distribution" below.## Requirements
In order to build the examples, you'll need the library and header files
for [FFmpeg 6](https://ffmpeg.org/download.html) installed.The `chromaprint` library is also
required for fingerprinting audio files and SDL2 for the video player.### MacOS
On Macintosh with [homebrew](http://bew.sh/), for example:
```bash
brew install ffmpeg@6 chromaprint make
brew link ffmpeg@6
```### Debian
If you're using Debian you may not be able to get the ffmpeg 6 unless you first of all add the debi-multimedia repository.
You can do this by adding the following line to your `/etc/apt/sources.list` file:```bash
# Run commands as privileged user
echo "deb https://www.deb-multimedia.org $(lsb_release -sc) main" >> /etc/apt/sources.list
apt update -y -oAcquire::AllowInsecureRepositories=true
apt install -y --force-yes deb-multimedia-keyring
```Then you can proceed to install the ffmpeg 6 and the other dependencies:
```bash
# Run commands as privileged user
apt install -y libavcodec-dev libavdevice-dev libavfilter-dev libavutil-dev libswscale-dev libswresample-dev
apt install -y libchromaprint-dev
apt install -y libsdl2-dev
```### Docker Container
TODO
## Examples
There are some examples in the `cmd` folder of the main repository on how to use
the package. The various make targets are:* `make all` will perform tests, build all examples and the backend API;
* `make test` will perform tests;
* `make cmd` will build example command-line tools into the `build` folder;
* `make clean` will remove all build artifacts.There are also some targets to build a docker image:
* `DOCKER_REGISTRY=docker.io/user make docker` will build a docker image;
* `DOCKER_REGISTRY=docker.io/user make docker-push` will push the docker image to the registry.For example,
```bash
git clone [email protected]:djthorpe/go-media.git
cd go-media
DOCKER_REGISTRY=ghcr.io/mutablelogic make docker
```There are a variety of types of object needed as part of media processing.
All examples require a `Manager` to be created, which is used to enumerate all supported formats
and open media files and byte streams.* `Manager` is the main entry point for the package. It is used to open media files and byte streams,
and enumerate supported formats, codecs, pixel formats, etc.
* `Media` is a hardware device, file or byte stream. It contains metadata, artwork, and streams.
* `Decoder` is used to demultiplex media streams. Create a decoder and enumerate the streams which
you'd like to demultiplex. Provide the audio and video parameters if you want to resample or
reformat the streams.
* `Encoder` is used to multiplex media streams. Create an encoder and send the output of the
decoder to reencode the streams.### Demultiplexing
```go
package mainimport (
media "github.com/mutablelogic/go-media"
)func main() {
manager, err := media.NewManager()
if err != nil {
log.Fatal(err)
}// Open a media file for reading. The format of the file is guessed.
// Alteratively, you can pass a format as the second argument. Further optional
// arguments can be used to set the format options.
file, err := manager.Open(os.Args[1], nil)
if err != nil {
log.Fatal(err)
}
defer file.Close()// Choose which streams to demultiplex - pass the stream parameters
// to the decoder. If you don't want to resample or reformat the streams,
// then you can pass nil as the function and all streams will be demultiplexed.
decoder, err := file.Decoder(func (stream media.Stream) (media.Parameters, error) {
return stream.Parameters(), nil
}
if err != nil {
log.Fatal(err)
}// Demuliplex the stream and receive the packets. If you don't want to
// process the packets yourself, then you can pass nil as the function
if err := decoder.Demux(context.Background(), func(_ media.Packet) error {
// Each packet is specific to a stream. It can be processed here
// to receive audio or video frames, then resize or resample them,
// for example. Alternatively, you can pass the packet to an encoder
// to remultiplex the streams without processing them.
return nil
}); err != nil {
log.Fatal(err)
})
}
```### Decoding - Video
This example shows you how to decode video frames from a media file into images, and
encode those images to JPEG format.```go
package mainimport (
"context"
"fmt"
"image/jpeg"
"io"
"log"
"os"
"path/filepath"// Packages
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"// Namespace imports
. "github.com/mutablelogic/go-media"
)func main() {
// Open a media file for reading. The format of the file is guessed.
input, err := ffmpeg.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}// Make a map function which can be used to decode the streams and set
// the parameters we want from the decode. The audio and video streams
// are resampled and resized to fit the parameters we pass back the decoder.
mapfunc := func(stream int, par *ffmpeg.Par) (*ffmpeg.Par, error) {
if par.Type() == VIDEO {
// Convert frame to yuv420p to frame size and rate as source
return ffmpeg.VideoPar("yuv420p", par.WidthHeight(), par.FrameRate()), nil
}
// Ignore other streams
return nil, nil
}// Make a folder where we're going to store the thumbnails
tmp, err := os.MkdirTemp("", "decode")
if err != nil {
log.Fatal(err)
}// Decode the streams and receive the video frame
// If the map function is nil, the frames are copied. In this example,
// we get a yuv420p frame at the same size as the original.
n := 0
err = input.Decode(context.Background(), mapfunc, func(stream int, frame *ffmpeg.Frame) error {
// Write the frame to a file
w, err := os.Create(filepath.Join(tmp, fmt.Sprintf("frame-%d-%d.jpg", stream, n)))
if err != nil {
return err
}
defer w.Close()// Convert to an image and encode a JPEG
if image, err := frame.Image(); err != nil {
return err
} else if err := jpeg.Encode(w, image, nil); err != nil {
return err
} else {
log.Println("Wrote:", w.Name())
}// End after 10 frames
n++
if n >= 10 {
return io.EOF
}
return nil
})
if err != nil {
log.Fatal(err)
}
}
```### Encoding - Audio and Video
This example shows you how to encode video and audio frames into a media file.
It creates a testcard signal overlayed with a timestamp, and a 1KHz tone at -5dB```go
package mainimport (
"fmt"
"io"
"log"
"os"// Packages
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
generator "github.com/mutablelogic/go-media/pkg/generator"
)// This example encodes an audio an video stream to a file
func main() {
// Create a new file with an audio and video stream
file, err := ffmpeg.Create(os.Args[1],
ffmpeg.OptStream(1, ffmpeg.VideoPar("yuv420p", "1024x720", 30)),
ffmpeg.OptStream(2, ffmpeg.AudioPar("fltp", "mono", 22050)),
)
if err != nil {
log.Fatal(err)
}
defer file.Close()// Make an video generator which can generate frames with the same
// parameters as the video stream
video, err := generator.NewEBU(file.Stream(1).Par())
if err != nil {
log.Fatal(err)
}
defer video.Close()// Make an audio generator which can generate a 1KHz tone
// at -5dB with the same parameters as the audio stream
audio, err := generator.NewSine(1000, -5, file.Stream(2).Par())
if err != nil {
log.Fatal(err)
}
defer audio.Close()// Write 90 seconds, passing video and audio frames to the encoder
// and returning io.EOF when the duration is reached
duration := float64(90)
err = file.Encode(func(stream int) (*ffmpeg.Frame, error) {
var frame *ffmpeg.Frame
switch stream {
case 1:
frame = video.Frame()
case 2:
frame = audio.Frame()
}
if frame != nil && frame.Ts() < duration {
return frame, nil
}
return nil, io.EOF
}, nil)
if err != nil {
log.Fatal(err)
}
}
```### Multiplexing
TODO
### Retrieving Metadata and Artwork from a media file
Here is an example of opening a media file and retrieving metadata and artwork.
You have to read the artwork separately from the metadata.```go
package mainimport (
"log"
"os"// Packages
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
)func main() {
// Open a media file for reading. The format of the file is guessed.
reader, err := ffmpeg.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
defer reader.Close()// Retrieve all the metadata from the file, and display it. If you pass
// keys to the Metadata function, then only entries with those keys will be
// returned.
for _, metadata := range reader.Metadata() {
log.Print(metadata.Key(), " => ", metadata.Value())
}// Retrieve artwork by using the MetaArtwork key. The value is of type []byte.
// which needs to be converted to an image.
for _, artwork := range reader.Metadata(ffmpeg.MetaArtwork) {
mimetype := artwork.Value()
if mimetype != "" {
// Retrieve the data using the metadata.Bytes() method
log.Print("We got some artwork of mimetype ", mimetype)
}
}
}
```### Audio Fingerprinting
You can programmatically fingerprint audio files, compare fingerprints and identify music using the following packages:
* `sys/chromaprint` provides the implementation of the lower-level function calls
to chromaprint. The documentation is [here](https://pkg.go.dev/github.com/mutablelogic/go-media/sys/chromaprint)
* `pkg/chromaprint` provides the higher-level API for fingerprinting and identifying music. The documentation
is [here](https://pkg.go.dev/github.com/mutablelogic/go-media/pkg/chromaprint).You'll need an API key in order to use the [AcoustID](https://acoustid.org/) service. You can get a key
[here](https://acoustid.org/login).## Contributing & Distribution
__This module is currently in development and subject to change.__
Please do file feature requests and bugs [here](https://github.com/mutablelogic/go-media/issues).
The license is Apache 2 so feel free to redistribute. Redistributions in either source
code or binary form must reproduce the copyright notice, and please link back to this
repository for more information:> __go-media__\
> [https://github.com/mutablelogic/go-media/](https://github.com/mutablelogic/go-media/)\
> Copyright (c) 2021-2024 David Thorpe, All rights reserved.This software links to shared libraries of [FFmpeg](http://ffmpeg.org/) licensed under
the [LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html).## References
* https://ffmpeg.org/doxygen/6.1/index.html
* https://pkg.go.dev/github.com/mutablelogic/go-media