Code Monkey home page Code Monkey logo

dca's Introduction

dca Go report Build Status

dca is a audio file format that uses opus packets and json metadata.

This package implements a decoder, encoder and a helper streamer for dca v0 and v1.

Docs on GoDoc

There's also a standalone command you can use here

Usage

Encoding

// Encoding a file and saving it to disk
encodeSession := dca.EncodeFile("path/to/file.mp3", dca.StdEncodeOptions)
// Make sure everything is cleaned up, that for example the encoding process if any issues happened isnt lingering around
defer encodeSession.Cleanup()

output, err := os.Create("output.dca")
if err != nil {
    // Handle the error
}

io.Copy(output, encodeSession)

Decoding, the decoder automatically detects dca version aswell as if metadata was available

// inputReader is an io.Reader, like a file for example
decoder := dca.NewDecoder(inputReader)

for {
    frame, err := decoder.OpusFrame()
    if err != nil {
        if err != io.EOF {
            // Handle the error
        }
        
        break
    }
    
    // Do something with the frame, in this example were sending it to discord
    select{
        case voiceConnection.OpusSend <- frame:
        case <-time.After(time.Second):
            // We haven't been able to send a frame in a second, assume the connection is borked
            return
    }
}

Using the helper streamer, the streamer creates a pausable stream to Discord.

// Source is an OpusReader, both EncodeSession and decoder implements opusreader
done := make(chan error)
streamer := dca.NewStreamer(source, voiceConnection, done)
err := <- done
if err != nil && err != io.EOF {
    // Handle the error
}

Using this youtube-dl Go package, one can stream music to Discord from Youtube

// Change these accordingly
options := dca.StdEncodeOptions
options.RawOutput = true
options.Bitrate = 96
options.Application = "lowdelay"

videoInfo, err := ytdl.GetVideoInfo(videoURL)
if err != nil {
    // Handle the error
}

format := videoInfo.Formats.Extremes(ytdl.FormatAudioBitrateKey, true)[0]
downloadURL, err := videoInfo.GetDownloadURL(format)
if err != nil {
    // Handle the error
}

encodingSession, err := dca.EncodeFile(downloadURL.String(), options)
if err != nil {
    // Handle the error
}
defer encodingSession.Cleanup()
    
done := make(chan error)    
dca.NewStream(encodingSession, voiceConnection, done)
err := <- done
if err != nil && err != io.EOF {
    // Handle the error
}

Official Specifications

dca's People

Contributors

bwmarrin avatar fanadol avatar hirbodbehnam avatar jonas747 avatar lon9 avatar strum355 avatar tionis 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dca's Issues

ffmpeg not reconnect when youtube URL is expired

Hi, so i have been using your package for build my discord bot. Its great thank you.

I found this problem when i playing around with my bot. When playing music (from youtube using ytdl package) its stop in the middle of the song. The error said it's EOF. But the song is not finished yet.

When i print the encodingSession.FFMPEGMessages() its shows something like this:

ffmpeg message ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.17)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.2.2_2 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, matroska,webm, from 'https://r1---sn-h8oxupq-jb3e.googlevideo.com/videoplayback?c=WEB&clen=3527654&dur=217.701&ei=jG1zXvK2FsGDssUP07Gk-Aw&expire=1584644588&fvip=3&gir=yes&id=o-AJXrW4xcFCgVXlnPGCHr51o9dRz-dgyP9UvexvPh6ec3&initcwndbps=323750&ip=103.8.78.14&itag=251&keepalive=yes&lmt=1575023145707784&lsig=ABSNjpQwRQIgIjFTB6fN1SfHZ30_XtaFRYFq1NIpcqt0Vu4tCAJr8kACIQDixfhd0Rtib3QfmfKakfaTNMdR_Z2qXc8_gTyDmKQ0oA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&mh=mM&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h8oxupq-jb3e%2Csn-npoeenee&ms=au%2Crdu&mt=1584622906&mv=m&mvi=0&pcm2=no&pcm2cms=yes&pl=24&ratebypass=yes&requiressl=yes&sig=ADKhkGMwRQIhAP2gpJasp4VRgXqdPefpkyszHb2l90mnICnZr7nytENNAiAqagp5zDRdhtaxNyFzjjfjcbWiNuhdyi3ClDuKJed8eQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cpcm2%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&txp=5531432&vprv=1':
  Metadata:
    encoder         : google/video-file
  Duration: 00:03:37.70, start: -0.007000, bitrate: 129 kb/s
    Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
Stream mapping:
  Stream #0:0 -> #0:0 (opus (native) -> opus (libopus))
Press [q] to stop, [?] for help
Output #0, ogg, to 'pipe:1':
  Metadata:
    encoder         : Lavf58.29.100
    Stream #0:0(eng): Audio: opus (libopus), 48000 Hz, stereo, flt, 96 kb/s (default)
    Metadata:
      encoder         : Lavc58.54.100 libopus
[tls @ 0x7fa970e07580] Error in the pull function.
[matroska,webm @ 0x7fa971000c00] Read error
[tls @ 0x7fa970e07580] The specified session has been invalidated for some reason.
    Last message repeated 1 times
https://r1---sn-h8oxupq-jb3e.googlevideo.com/videoplayback?c=WEB&clen=3527654&dur=217.701&ei=jG1zXvK2FsGDssUP07Gk-Aw&expire=1584644588&fvip=3&gir=yes&id=o-AJXrW4xcFCgVXlnPGCHr51o9dRz-dgyP9UvexvPh6ec3&initcwndbps=323750&ip=103.8.78.14&itag=251&keepalive=yes&lmt=1575023145707784&lsig=ABSNjpQwRQIgIjFTB6fN1SfHZ30_XtaFRYFq1NIpcqt0Vu4tCAJr8kACIQDixfhd0Rtib3QfmfKakfaTNMdR_Z2qXc8_gTyDmKQ0oA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&mh=mM&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h8oxupq-jb3e%2Csn-npoeenee&ms=au%2Crdu&mt=1584622906&mv=m&mvi=0&pcm2=no&pcm2cms=yes&pl=24&ratebypass=yes&requiressl=yes&sig=ADKhkGMwRQIhAP2gpJasp4VRgXqdPefpkyszHb2l90mnICnZr7nytENNAiAqagp5zDRdhtaxNyFzjjfjcbWiNuhdyi3ClDuKJed8eQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cpcm2%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&txp=5531432&vprv=1: Input/output error
size=    2369kB time=00:03:24.30 bitrate=  95.0kbits/s speed=1.04x
video:0kB audio:2352kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.702825%

When i try to google this error, it's turn out that the youtube URL was expired. So the ffmpeg immediately return EOF.

The specified session has been invalidated for some reason.

I am able to solve this issue (maybe) to add reconnect flag in ffmpeg command. I will try to link my PR to this issue.

Thank you.

ReadMe Fix

Your readme is missing one vital piece in the example for using the ytdl package, which is to tell the voiceConnection that you have begun speaking.

e := voiceConnection.Speaking(true)
if e != nil {
   // handle error
}

Sound plays 2x as fast if set 40 as FrameDuration

I tried play sound with Discord VC.

Code:

option := &dca.EncodeOptions{
	Volume:           256,
	Channels:         2,
	FrameRate:        48000,
	FrameDuration:    40,
	Bitrate:          96,
	Application:      dca.AudioApplicationAudio,
	CompressionLevel: 10,
	PacketLoss:       1,
	BufferedFrames:   1024,
	VBR:              true,
}
encoder, err := dca.EncodeMem(r, option)
if err != nil {
	return err
}

for {
	frame, err := encoder.OpusFrame()
	if err == io.EOF {
		break
	}
	if err != nil {
		return err
	}

	conn.OpusSend <- frame
}

This plays it 2x as fast. Setting FrameDuration: 20 fix it. It's expected behavior?

Or maybe Discord side problem?(Sorry, but really I'm not familiar with DCA or Opus.)

[Request] Filtering Mid-Stream

Studying the source of dca and its current setup, I've been doing my best to try and research if there's any possible way to filter audio output mid-stream using FFMPEG and some message with an STDIN pipe. My reason for trying to figure this out is I absolutely love the simplistic library dca provides (and I even plan on adding a few things of my own in the near future with a pull request), however it seems almost impossible to change the volume mid-stream or apply equalizer effects mid-stream unless FFMPEG specifically allows it.

If you have the knowledge on how to do this, it'd be an amazing feature for dca to have. Even if you don't feel like doing it yourself, I'd be happy to help add it for things like changing the volume mid-stream should you or anyone else know how to go about it.

Thanks in advance for anything pertaining this,
JoshuaDoes

Output becomes an empty file

I wrote the code below, but the file size of output.dca is 0 byte. How do it work fine?

package main

import (
	"io"
	"os"

	"github.com/jonas747/dca"
)

func main() {
	opts := dca.StdEncodeOptions
	opts.RawOutput = true
	encodeSession, err := dca.EncodeFile("hello.wav", opts)
	if err != nil {
		panic(err)
	}
	defer encodeSession.Cleanup()

	output, err := os.Create("output.dca")
	if err != nil {
		panic(err)
	}

	io.Copy(output, encodeSession)
}

Environment

Mac OS X
ffmpeg 3.3.4

Returning "EOF" error in the beginning of the file.

Hello. I'm trying to stream audio to Discord. I used example from README but I always get "EOF" error from dca.NewStream.
I debugged the source files of this package but I didn't find a reason. Also I tried to pass local file not URL but got the same problem.

encodeSession, err := dca.EncodeFile(StreamURL, options)
if err != nil {
        log.Println("ERR: dca.EncodeFile(StreamURL, options): " + err.Error())
        return err
}
encoder = encodeSession
defer encodeSession.Cleanup()
done := make(chan error)
stream := dca.NewStream(encodeSession, voice, done)

for err := range done {
        if err != nil && err != io.EOF {
	        log.Println("FATA: An error occurred", err)
        }
        
        if err == io.EOF {
	        encodeSession.Cleanup()
	        break
        }
}
return nil

Youtube Stream EOFs in the middle of stream

So this is a weird issue that I kind of understand. From what I know, Google times out because it expects everything to be buffered, when in reality FFMPEG buffers slowly as it goes on. I don't know how easy this is to fix, but it's rather annoying to get an EOF in the middle of a song that's longer than a minute.

[Feature Request] Change Volume Mid-stream

As noted in #10 volume can currently not be changed mid stream without changing the code. It would be very handy for the encodingsession to expose a function that modifies a volume multiplier.

Youtube stream gives no audio output

Soo this is a weird issue I'm having.
Using this to stream to discord with a file I encode from my pc works perfectly.
I looked at the example in the Readme to make it stream from youtube links.
Sadly it simply doesn't play them. I don't know if this is a common thing and is fixed easily but I couldn't find any help from people who've used this before. Hope you know what's wrong!

Option reconnect not found

I've updated ffmpeg to 4.2.2 with Homebrew and the error is occurred.

ffmpeg: stable 4.2.2 (bottled), HEAD
Play, record, convert, and stream audio and video
https://ffmpeg.org/
/usr/local/Cellar/ffmpeg/4.2.2_3 (287 files, 57MB) *
  Poured from bottle on 2020-05-01 at 22:30:05
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/ffmpeg.rb
==> Dependencies
Build: nasm ✔, pkg-config ✔, texi2html ✔
Required: aom ✔, fontconfig ✔, freetype ✔, frei0r ✔, gnutls ✔, lame ✔, libass ✔, libbluray ✔, libsoxr ✔, libvidstab ✔, libvorbis ✔, libvpx ✔, opencore-amr ✔, openjpeg ✔, opus ✔, rtmpdump ✔, rubberband ✔, sdl2 ✔, snappy ✔, speex ✔, srt ✔, tesseract ✔, theora ✔, webp ✔, x264 ✔, x265 ✔, xvid ✔, xz ✔
==> Options
--HEAD
	Install HEAD version
==> Analytics
install: 96,128 (30 days), 274,858 (90 days), 1,031,225 (365 days)
install-on-request: 74,313 (30 days), 206,361 (90 days), 751,167 (365 days)
build-error: 0 (30 days)

2020/05/03 17:37:35 ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.17)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.2.2_3 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags=-fno-stack-check --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Option reconnect not found.

Stopping music example running in go routine?

Using this example:

options := dca.StdEncodeOptions
options.RawOutput = true
options.Bitrate = 96
options.Application = "lowdelay"

videoInfo, err := ytdl.GetVideoInfo(videoURL)
if err != nil {
    // Handle the error
}

format := videoInfo.Formats.Extremes(ytdl.FormatAudioBitrateKey, true)[0]
downloadURL, err := videoInfo.GetDownloadURL(format)
if err != nil {
    // Handle the error
}

encodingSession, err := dca.EncodeFile(downloadURL.String(), options)
if err != nil {
    // Handle the error
}
defer encodingSession.Cleanup()
    
done := make(chan error)    
dca.NewStream(encodingSession, voiceConnection, done)
err := <- done
if err != nil && err != io.EOF {
    // Handle the error
}

how would i stop the music from playing? Can i use the done channel created by the stream? I'm using that code in a go routine and need to stop it from another go routine.

Error parsing ffmpeg stats: strconv.ParseFloat: parsing "N": invalid syntax

The error in the title clogs the terminal as the library struggles to play the first few seconds of any audio file without stuttering, and it eventually just outright changes to Voice connection closed, then inevitably timeout waiting for voice, then inevitably it panics with invalid memory address or nil pointer dereference.

A video of the error can be seen here

My code is as follows:

// start the audio session
options := dca.StdEncodeOptions
encodingSession, r := dca.EncodeFile("HOTEL_MARIO_TONE.mp3", options)
er(r)
defer encodingSession.Cleanup()

done := make(chan error)
dca.NewStream(encodingSession, vc, done)
err = <- done
if(err != nil && err != io.EOF) {
	// keep trucking, actually.
	fmt.Println(err)
}

My ffmpeg version is 5.1, however this happened on 5.0 as well. I don't think the audio file is important because this error persists across three of them, but here it is (note that the fact that it's one second long doesn't matter, it does this with many other longer fiels as mentioned previously)

ffmpeg Option reconnect not found.

Hi, I´m getting the following error while encoding a .mp3 file:

ffmpeg version 4.2.4-1ubuntu0.1 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 9 (Ubuntu 9.3.0-10ubuntu2) configuration: --prefix=/usr --extra-version=1ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56. 31.100 / 56. 31.100 libavcodec 58. 54.100 / 58. 54.100 libavformat 58. 29.100 / 58. 29.100 libavdevice 58. 8.100 / 58. 8.100 libavfilter 7. 57.100 / 7. 57.100 libavresample 4. 0. 0 / 4. 0. 0 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Option reconnect not found.

Ubuntu 20.04 FFMPEG 4.2.4

How to Install and use

Hey, so I am on Windows and I dont really understand the instructions... What do I need and what commands do I have to execute in the cloned folder?

Encoding not working because of volume argument on FFmpeg command

I was always getting an empty session when encoding, without getting any errors.

I manually tried the command used to encode and got this:

Unrecognized option 'vol'.
Error splitting the argument list: Option not found

So i checked the arguments the package is sending (encode.go):

// Launch ffmpeg with a variety of different fruits and goodies mixed togheter
	args := []string{
		"-stats",
		"-i", inFile,
		"-reconnect", "1",
		"-reconnect_at_eof", "1",
		"-reconnect_streamed", "1",
		"-reconnect_delay_max", "2",
		"-map", "0:a",
		"-acodec", "libopus",
		"-f", "ogg",
		"-vbr", vbrStr,
		"-compression_level", strconv.Itoa(e.options.CompressionLevel),
		"-vol", strconv.Itoa(e.options.Volume),
		"-ar", strconv.Itoa(e.options.FrameRate),
		"-ac", strconv.Itoa(e.options.Channels),
		"-b:a", strconv.Itoa(e.options.Bitrate * 1000),
		"-application", string(e.options.Application),
		"-frame_duration", strconv.Itoa(e.options.FrameDuration),
		"-packet_loss", strconv.Itoa(e.options.PacketLoss),
		"-threads", strconv.Itoa(e.options.Threads),
		"-ss", strconv.Itoa(e.options.StartTime),
	}

I dont know if this was working for an older version of FFmpeg, or it's just a Windows problem, but vol does not exists as an argument.

Removing it correctly encodes the file.

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.