{"id":13908640,"url":"https://github.com/AlexEidt/Vidio","last_synced_at":"2025-07-18T07:32:02.592Z","repository":{"id":43019636,"uuid":"430938546","full_name":"AlexEidt/Vidio","owner":"AlexEidt","description":"FFmpeg wrapper providing simple, cross-platform Video I/O, GIF Creation, and Webcam Streaming in Go.","archived":false,"fork":false,"pushed_at":"2024-02-16T18:02:08.000Z","size":653,"stargazers_count":348,"open_issues_count":2,"forks_count":15,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-08-07T23:57:42.962Z","etag":null,"topics":["ffmpeg-wrapper","frame-by-frame","gif-creator","video-io","webcam-streaming"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/AlexEidt/Vidio","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexEidt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-23T02:52:28.000Z","updated_at":"2024-07-25T01:16:28.000Z","dependencies_parsed_at":"2024-04-16T04:46:05.595Z","dependency_job_id":"0183d1f8-9415-42b4-bd1f-731497f49a61","html_url":"https://github.com/AlexEidt/Vidio","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexEidt%2FVidio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexEidt%2FVidio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexEidt%2FVidio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexEidt%2FVidio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexEidt","download_url":"https://codeload.github.com/AlexEidt/Vidio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226372302,"owners_count":17614661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffmpeg-wrapper","frame-by-frame","gif-creator","video-io","webcam-streaming"],"created_at":"2024-08-06T23:02:53.020Z","updated_at":"2024-11-25T17:31:50.473Z","avatar_url":"https://github.com/AlexEidt.png","language":"Go","funding_links":[],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"# Vidio\n\nA simple Video I/O library written in Go. This library relies on [FFmpeg](https://www.ffmpeg.org/), and [FFProbe](https://www.ffmpeg.org/) which must be downloaded before usage and added to the system path.\n\nAll frames are encoded and decoded in 8-bit RGBA format.\n\nFor Audio I/O using FFmpeg, see the [`aio`](https://github.com/AlexEidt/aio) project.\n\n## Installation\n\n```\ngo get github.com/AlexEidt/Vidio\n```\n\n## `Video`\n\nThe `Video` struct stores data about a video file you give it. The code below shows an example of sequentially reading the frames of the given video.\n\nCalling the `Read()` function will fill in the `Video` struct `framebuffer` with the next frame data as 8-bit RGBA data, stored in a flattened byte array in row-major order where each pixel is represented by four consecutive bytes representing the R, G, B and A components of that pixel. Note that the A (alpha) component will always be 255. When iteration over the entire video file is not required, we can lookup a specific frame by calling `ReadFrame(n int)`. By calling `ReadFrames(n ...int)`, we can immediately access multiple frames as a slice of RGBA images and skip the `framebuffer`.\n\n```go\nvidio.NewVideo(filename string) (*vidio.Video, error)\nvidio.NewVideoStreams(filename string) ([]*vidio.Video, error)\n\nFileName() string\nWidth() int\nHeight() int\nDepth() int\nBitrate() int\nFrames() int\nStream() int\nDuration() float64\nFPS() float64\nCodec() string\nHasStreams() bool\nFrameBuffer() []byte\nMetaData() map[string]string\nSetFrameBuffer(buffer []byte) error\n\nRead() bool\nReadFrame(n int) error\nReadFrames(n ...int) ([]*image.RGBA, error)\nClose()\n```\n\nIf all frames have been read, `video` will be closed automatically. If not all frames are read, call `video.Close()` to close the video.\n\n## `Camera`\n\nThe `Camera` can read from any cameras on the device running `Vidio`. It takes in the stream index. On most machines the webcam device has index 0.\n\n```go\nvidio.NewCamera(stream int) (*vidio.Camera, error)\n\nName() string\nWidth() int\nHeight() int\nDepth() int\nFPS() float64\nCodec() string\nFrameBuffer() []byte\nSetFrameBuffer(buffer []byte) error\n\nRead() bool\nClose()\n```\n\n## `VideoWriter`\n\nThe `VideoWriter` is used to write frames to a video file. The only required parameters are the output file name, the width and height of the frames being written, and an `Options` struct. This contains all the desired properties of the new video you want to create.\n\n```go\nvidio.NewVideoWriter(filename string, width, height int, options *vidio.Options) (*vidio.VideoWriter, error)\n\nFileName() string\nStreamFile() string\nWidth() int\nHeight() int\nBitrate() int\nLoop() int\nDelay() int\nMacro() int\nFPS() float64\nQuality() float64\nCodec() string\n\nWrite(frame []byte) error\nClose()\n```\n\n```go\ntype Options struct {\n\tBitrate    int     // Bitrate.\n\tLoop       int     // For GIFs only. -1=no loop, 0=infinite loop, \u003e0=number of loops.\n\tDelay      int     // Delay for final frame of GIFs in centiseconds.\n\tMacro      int     // Macroblock size for determining how to resize frames for codecs.\n\tFPS        float64 // Frames per second for output video.\n\tQuality    float64 // If bitrate not given, use quality instead. Must be between 0 and 1. 0:best, 1:worst.\n\tCodec      string  // Codec for video.\n\tStreamFile string  // File path for extra stream data.\n}\n```\n\nThe `Options.StreamFile` parameter is intended for users who wish to process a video stream and keep the audio (or other streams). Instead of having to process the video and store in a file and then combine with the original audio later, the user can simply pass in the original file path via the `Options.StreamFile` parameter. This will combine the video with all other streams in the given file (Audio, Subtitle, Data, and Attachments Streams) and will cut all streams to be the same length. **Note that `Vidio` is not a audio/video editing library.**\n\nThis means that adding extra stream data from a file will only work if the filename being written to is a container format.\n\n## Images\n\n`Vidio` provides some convenience functions for reading and writing to images using an array of bytes. Currently, only `png` and `jpeg` formats are supported. When reading images, an optional `buffer` can be passed in to avoid array reallocation.\n\n```go\nRead(filename string, buffer ...[]byte) (int, int, []byte, error)\nWrite(filename string, width, height int, buffer []byte) error\n```\n\n## Examples\n\nCopy `input.mp4` to `output.mp4`. Copy the audio from `input.mp4` to `output.mp4` as well.\n\n```go\nvideo, _ := vidio.NewVideo(\"input.mp4\")\noptions := vidio.Options{\n\tFPS: video.FPS(),\n\tBitrate: video.Bitrate(),\n}\nif video.HasStreams() {\n\toptions.StreamFile = video.FileName()\n}\n\nwriter, _ := vidio.NewVideoWriter(\"output.mp4\", video.Width(), video.Height(), \u0026options)\n\ndefer writer.Close()\n\nfor video.Read() {\n    writer.Write(video.FrameBuffer())\n}\n```\n\nRead 1000 frames of a webcam stream and store in `output.mp4`.\n\n```go\nwebcam, _ := vidio.NewCamera(0)\ndefer webcam.Close()\n\noptions := vidio.Options{FPS: webcam.FPS()}\nwriter, _ := vidio.NewVideoWriter(\"output.mp4\", webcam.Width(), webcam.Height(), \u0026options)\ndefer writer.Close()\n\ncount := 0\nfor webcam.Read() \u0026\u0026 count \u003c 1000 {\n\twriter.Write(webcam.FrameBuffer())\n\tcount++\n}\n```\n\nCreate a gif from a series of `png` files enumerated from 1 to 10 that loops continuously with a final frame delay of 1000 centiseconds.\n\n```go\nw, h, _, _ := vidio.Read(\"1.png\") // Get frame dimensions from first image\n\noptions := vidio.Options{FPS: 1, Loop: 0, Delay: 1000}\ngif, _ := vidio.NewVideoWriter(\"output.gif\", w, h, \u0026options)\ndefer gif.Close()\n\nfor i := 1; i \u003c= 10; i++ {\n\tw, h, img, _ := vidio.Read(fmt.Sprintf(\"%d.png\", i))\n\tgif.Write(img)\n}\n```\n\nWrite all frames of `video.mp4` as `jpg` images.\n\n```go\nvideo, _ := vidio.NewVideo(\"video.mp4\")\n\nimg := image.NewRGBA(image.Rect(0, 0, video.Width(), video.Height()))\nvideo.SetFrameBuffer(img.Pix)\n\nframe := 0\nfor video.Read() {\n\tf, _ := os.Create(fmt.Sprintf(\"%d.jpg\", frame))\n\tjpeg.Encode(f, img, nil)\n\tf.Close()\n\tframe++\n}\n```\n\nWrite the last frame of `video.mp4` as `jpg` image (without iterating over all video frames).\n\n```go\nvideo, _ := video.NewVideo(\"video.mp4\")\n\nimg := image.NewRGBA(image.Rect(0, 0, video.Width(), video.Height()))\nvideo.SetFrameBuffer(img.Pix)\n\nvideo.ReadFrame(video.Frames() - 1)\n\nf, _ := os.Create(fmt.Sprintf(\"%d.jpg\", video.Frames() - 1))\njpeg.Encode(f, img, nil)\nf.Close()\n```\n\nWrite the first and last frames of `video.mp4` as `jpg` images (without iterating over all video frames).\n\n```go\nvideo, _ := vidio.NewVideo(\"video.mp4\")\n\nframes, _ := video.ReadFrames(0, video.Frames() - 1)\n\nfor index, frame := range frames {\n\tf, _ := os.Create(fmt.Sprintf(\"%d.jpg\", index))\n\tjpeg.Encode(f, frame, nil)\n\tf.Close()\n}\n```\n\n# Acknowledgements\n\n* Special thanks to [Zulko](http://zulko.github.io/) and his [blog post](http://zulko.github.io/blog/2013/09/27/read-and-write-video-frames-in-python-using-ffmpeg/) about using FFmpeg to process video.\n* The [ImageIO-FFMPEG](https://github.com/imageio/imageio-ffmpeg/) project on GitHub.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlexEidt%2FVidio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAlexEidt%2FVidio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAlexEidt%2FVidio/lists"}