Search code examples
c++vlclibvlc

Convert an audio to uncompress wav by libvlc


  • OS : win10 64 bits
  • compiler : vc2017 64bits
  • vlc version : 3.0.9.2 from here

Source codes

#include <vlc/vlc.h>

#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include <vector>

void libvlc_callback(libvlc_event_t const *event, void*)
{
    switch (event->type) {
    case libvlc_MediaMetaChanged:
        std::cout<<__func__<<": libvlc_MediaMetaChanged = "<<event->u.media_meta_changed.meta_type<<std::endl;
        break;
    case libvlc_MediaSubItemAdded:
        std::cout<<__func__<<": libvlc_MediaSubItemAdded = "<<event->u.media_subitem_added.new_child<<std::endl;
        break;
    case libvlc_MediaDurationChanged:
        std::cout<<__func__<<": libvlc_MediaDurationChanged = "
                <<event->u.media_duration_changed.new_duration<<std::endl;
        break;
    case libvlc_MediaParsedChanged:
        std::cout<<__func__<<": libvlc_MediaParsedChanged = "<<event->u.media_parsed_changed.new_status<<std::endl;
        break;
    case libvlc_MediaFreed:
        std::cout<<__func__<<": libvlc_MediaFreed = "<<event->u.media_freed.md<<std::endl;
        break;
    case libvlc_MediaStateChanged:
        std::cout<<__func__<<":libvlc_MediaStateChanged = "<<event->u.media_state_changed.new_state<<std::endl;
        break;
    default:
        break;
    }
}

std::vector<libvlc_event_e> create_events()
{
    return {libvlc_MediaMetaChanged,
                libvlc_MediaSubItemAdded,
                libvlc_MediaDurationChanged,
                libvlc_MediaParsedChanged,
                libvlc_MediaFreed,
                libvlc_MediaStateChanged};
}

int main()
{
    libvlc_instance_t *inst = libvlc_new(0, nullptr);
    char const *location = "C:/Users/ssss/audio/audio.mp3";
    libvlc_media_t *vlc_media = libvlc_media_new_location(inst, location);
    libvlc_event_manager_t *vlc_events = libvlc_media_event_manager(vlc_media);

    for(libvlc_event_e const &event : create_events()){
        libvlc_event_attach(vlc_events, event, libvlc_callback, nullptr);
    }

    libvlc_media_add_option(vlc_media, "--sout='#transcode{acodec=s16l, ab=16, channels=1, samplerate=16000}:"
                                       "std{access=file, mux=wav, "
                                       "dst=\"audio.wav\"}'");

    std::this_thread::sleep_for(std::chrono::seconds(10));

    libvlc_media_release(vlc_media);
    libvlc_release(inst);
}

The output I got are

main libvlc debug: VLC media player - 3.0.9.2 Vetinari
main libvlc debug: Copyright © 1996-2020 the VideoLAN team
main libvlc debug: revision 3.0.9.2-0-gd4c1aefe4d
main libvlc debug: configured with ../extras/package/win32/../../../configure  '--enable-update-check' '--enable-lua' '--enable-faad' '--enable-flac' '--enable-theora' '--enable-avcodec' '--enable-merge-ffmpeg' '--enable-dca' '--enable-mpc' '--enable-libass' '--enable-schroedinger' '--enable-realrtsp' '--enable-live555' '--enable-dvdread' '--enable-shout' '--enable-goom' '--enable-caca' '--enable-qt' '--enable-skins2' '--enable-sse' '--enable-mmx' '--enable-libcddb' '--enable-zvbi' '--disable-telx' '--enable-nls' '--host=x86_64-w64-mingw32' '--with-breakpad=https://win.crashes.videolan.org' 'host_alias=x86_64-w64-mingw32' 'PKG_CONFIG_LIBDIR=/home/jenkins/workspace/vlc-release/windows/vlc-release-win32-x64/contrib/x86_64-w64-mingw32/lib/pkgconfig'
main libvlc debug: using multimedia timers as clock source
main libvlc debug:  min period: 1 ms, max period: 1000000 ms
main libvlc debug: searching plug-in modules
main libvlc debug: loading plugins cache file C:\vlc-3.0.9.2-win64\plugins\plugins.dat
main libvlc warning: cannot read C:\vlc\vlc-3.0.9.2-win64\plugins\plugins.dat: No such file or directory
main libvlc debug: recursively browsing `C:\vlc\vlc-3.0.9.2-win64\plugins'
main libvlc debug: plug-ins loaded: 494 modules
main logger debug: looking for logger module matching "any": 2 candidates
main logger debug: using logger module "console"
main libvlc debug: translation test: code is "C"
main keystore debug: looking for keystore module matching "memory": 3 candidates
main keystore debug: using keystore module "memory"
main libvlc debug: CPU has capabilities MMX MMXEXT SSE SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 FPU 
libvlc_callback: libvlc_MediaFreed = 000001DBD602CC50
main libvlc debug: exiting
main libvlc debug: no exit handler
main libvlc debug: removing all interfaces
main keystore debug: removing module "memory"

I cannot see any audio.wav generated in the folder, which step I missed or done it wrong? Thanks

Edit: pass parameters into libvlc_new

const char * const vlc_args[] = {
                  "--sout", 
   "#transcode{acodec=s16l,channels=2,samplerate=44100}:std{access=file,mux=wav,dst=\"C:/my_path/clip_0002.wav\"}",
    "C:/my_path/audio.wav"};
    libvlc_instance_t *inst = libvlc_new(3, vlc_args);

    std::this_thread::sleep_for(std::chrono::seconds(60));
    libvlc_release(inst);

It give me output message

main libvlc debug: exiting
main libvlc debug: no exit handler
main libvlc debug: removing all interfaces
main keystore debug: removing module "memory"

Don't know why the output file 'audio.wav' never generated in the folder


Solution

  • Found a solution, you need to play the media and open the file correctly, for simplicity I use "libvlc_media_new_path" in this example, if you are using "libvlc_media_new_location", remember to append "file:///" before the location and change to native separator.

    #include "core/vlc_error.hpp"
    
    #include <vlc/vlc.h>
    
    #include <chrono>
    #include <iostream>
    #include <string>
    #include <thread>
    #include <vector>
    
    #include <QString>
    
    void libvlc_callback(libvlc_event_t const *event, void*)
    {
        switch (event->type) {
        case libvlc_MediaMetaChanged:
            std::cout<<__func__<<": libvlc_MediaMetaChanged = "<<event->u.media_meta_changed.meta_type<<std::endl;
            break;
        case libvlc_MediaSubItemAdded:
            std::cout<<__func__<<": libvlc_MediaSubItemAdded = "<<event->u.media_subitem_added.new_child<<std::endl;
            break;
        case libvlc_MediaDurationChanged:
            std::cout<<__func__<<": libvlc_MediaDurationChanged = "
                    <<event->u.media_duration_changed.new_duration<<std::endl;
            break;
        case libvlc_MediaParsedChanged:
            std::cout<<__func__<<": libvlc_MediaParsedChanged = "<<event->u.media_parsed_changed.new_status<<std::endl;
            break;
        case libvlc_MediaFreed:
            std::cout<<__func__<<": libvlc_MediaFreed = "<<event->u.media_freed.md<<std::endl;
            break;
        case libvlc_MediaStateChanged:
            std::cout<<__func__<<":libvlc_MediaStateChanged = "<<event->u.media_state_changed.new_state<<std::endl;
            break;
        default:
            break;
        }
    }
    
    std::vector<libvlc_event_e> create_events()
    {
        return {libvlc_MediaMetaChanged,
                    libvlc_MediaSubItemAdded,
                    libvlc_MediaDurationChanged,
                    libvlc_MediaParsedChanged,
                    libvlc_MediaListEndReached,
                    libvlc_MediaFreed,
                    libvlc_MediaStateChanged};
    }
    
    int main()
    {
        libvlc_instance_t *inst = libvlc_new(0, nullptr);
        char const *location = "clip_0002.wav";
        libvlc_media_t *vlc_media = libvlc_media_new_path(inst, location);
        libvlc_event_manager_t *vlc_events = libvlc_media_event_manager(vlc_media);
    
        for(libvlc_event_e const &event : create_events()){
            libvlc_event_attach(vlc_events, event, libvlc_callback, nullptr);
        }
    
        QString const cmd("transcode{acodec=s16l, ab=16, channels=1, samplerate=16000}:"
                          "std{access=file, mux=wav, "
                          "dst='audio.wav'}");
        QString config = ":sout=#duplicate{dst=display,dst=\"%1\"}";
        config = config.arg(cmd);
        std::cout<<"-------------------------"<<std::endl;
        std::cout<<config.toStdString()<<std::endl;
        libvlc_media_add_option(vlc_media, ":sout-all");
        qt_vlc::vlc_error::show_err_msg();
        libvlc_media_add_option(vlc_media, config.toUtf8().data());
        qt_vlc::vlc_error::show_err_msg();     
    
        libvlc_media_player_t *vlc_player = libvlc_media_player_new_from_media(vlc_media);
        libvlc_audio_set_mute(vlc_player, true);
        libvlc_media_player_play(vlc_player);
    
        while(1){
            qt_vlc::vlc_error::show_err_msg();
            if(libvlc_media_get_state(vlc_media) == libvlc_Ended){
                break;
            }
            std::cout<<"media state = "<<libvlc_media_get_state(vlc_media)<<std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    
        libvlc_media_player_release(vlc_player);
        libvlc_media_release(vlc_media);
        libvlc_release(inst);
    }
    

    You can convert video to audio by this solution too, problem is it will show the video when converting, finding a way to hide the video.