Products            Buy            Support Forum            Professional            About            Codec Central
Results 1 to 7 of 7

Thread: Keeping libraries in sync

  1. #1

    Keeping libraries in sync

    I have around 15'000 flac files in my library. I have converted them to mp3 using batch converter. This took around 18 hours. Now I am wondering how I can keep the flac and mp3 libraries in sync. Is there a function somewhere in batch converter that allows a changes in the flac library to propagate through to the mp3 library without manually reconverting the files concerned?
    Thanks and regards

  2. #2
    dBpoweramp Guru
    Join Date
    Dec 2006

    Re: Keeping libraries in sync


    fwiw, I use mediamonkey to achieve basically the same thing and it works well enough for my needs.

    essentially, I fool MM into thinking a shared network drive is a mp3 device, then setup a sync profile to sync my entire mixed flac/mp3 library to a separate only mp3 library. MM converts and updates the mp3 library whenever I tell it to sync.

    I am sure the same thing could be accomplished with foobar or most any other music library manager with generic syncing and conversion capabilities.
    Last edited by Teknojnky; 02-02-2011 at 04:01 PM.

  3. #3
    Join Date
    Apr 2002

    Re: Keeping libraries in sync

    You can set batch converter to convert all FLAC to mp3 and when presented with the overwrite page select 'No to All', only missing tracks are converted.

  4. #4

    Re: Keeping libraries in sync

    Thanks to both of you. Will try both suggestions.

  5. #5
    dBpoweramp Guru
    Join Date
    Dec 2006

    Re: Keeping libraries in sync

    spoon's solution will not update any tracks who's tags have changed, nor will it delete tracks that have removed/moved.

  6. #6

    Join Date
    Dec 2010

    Re: Keeping libraries in sync

    I have the same problem and asked for this feature in the wish list.

    Other thing, to use Spoon's suggested workaround, would be great to have a checkbox "Overwrite files without asking" and "Do not overwrite existing files without asking" in the conversion setup screen so that, once launched, we do not have to wait overwrite check to say if we want to overwrite or not. Just click Convert and go to bed ! :-)

    EDIT : actually, my request in the wish list was not exactly what you asked for (keep Flac & converted files sync) : it was to be able to launch Batch Converter with predefined setting as a scheduled task, so that it can run every night.
    Last edited by jholvoet; 02-09-2011 at 04:27 PM.

  7. #7
    dBpoweramp Enthusiast
    Join Date
    Nov 2007

    Re: Keeping libraries in sync

    I wrote a Perl script to do pretty much this - my WHS/RipNAS box runs it once a day and converts my FLAC rips to MP4. I originally posted it here: http://forum.dbpoweramp.com/showpost...1&postcount=12

    ..but have since updated it to take care of deleting files in the output folder, to keep the MP4s in sync with the FLACs. It's not supremely clever, if files move or tags change, it will reencode rather than duplicating the move or just updating the tags.

    use File::Find::Rule;
    use File::Find;
    use File::StatCache qw( get_item_mtime );
    use Parallel::ForkManager;
    use MP4::Info;
    *blooper*   Configuration options
    *blooper*   =====================
    *blooper* Use forward slashes in place of backslashes for these paths
    my $source_dir  = 'D:/shares/Music/Ripped CDs';
    my $dest_dir    = 'D:/shares/Converted Music/Ripped CDs';
    *blooper* Case of source extension is important. Don't include the leading period.
    my $source_ext  = 'flac';
    my $dest_ext    = 'm4a';
    *blooper* Output codec and options.
    *blooper* It's easiest to set the desired options in CD Ripper and then look up the CLI syntax in the registry:
    *blooper* See the HKCU\Software\Illustrate\dBpoweramp\CDRipper\Profiles\(default) key (or whatever profile you configured)
    *blooper* The 'CodecCLI_<codec>' and 'DSPEffects' strings contain the values needed. Leave any backslashes as they are.
    my $dest_codec    = 'm4a Nero (AAC)';
    my $codec_options = ' -cli_encoder="C:\Program Files\Illustrate\dBpoweramp (Music Converter Reference)\encoder\m4a Nero (AAC)\neroAacEnc.exe" -cli_cmd="-q .45 -ignorelength -if - -of {qt}[outfile]{qt}" -selection="0,4,0" ';
    my $dsp_effects   = ' -dspeffect1="Volume Normalize= -mode={qt}rg{qt} -maxamp={qt}8{qt} -desiredb={qt}-0{qt} -adapt_wnd={qt}6000{qt} -fixed={qt}0{qt}" -dspeffect2="Bit Depth=-depth={qt}16{qt}" -dspeffect3="Delete Destination File on Error=" ';
    *blooper* dBpoweramp options.
    *blooper* The '-silent' flag is recommended to avoid overlapping progress output. Leave paths with backslashes.
    my $dmc_options   = ' -silent -error="D:\shares\Converted Music\Error Log.txt" ';
    *blooper* Log file. Use forward slashes in the path, leave blank to disable.
    my $logfile = 'D:/shares/Converted Music/Conversion Log.txt';
    *blooper* Set this to the number of CPUs/cores in your system, or 0 to disable multi-processing.
    my $number_of_cpus    = 2;
    *blooper* Location of dBpoweramp CoreConverter.exe (leave with backslashes here)
    my $coreconverter_exe = 'C:\Program Files\Illustrate\dBpoweramp (Music Converter Reference)\CoreConverter.exe';
    *blooper* There should be no need to edit anything below this line
    *blooper* ========================================================
    *blooper* Logging sub-routine
    sub logmsg {
      if ( $logfile ne "" ) {   *blooper* log to file if the logfile is defined
        open LOGFILE , ">>$logfile";
        print LOGFILE "$_[0]\n";
        print "$_[0]\n";   *blooper* also print to screen (unless running under wperl.exe)              
    *blooper* Find all source files
    my @srcfiles = File::Find::Rule->file()
                                                                    ->name( '*.' . $source_ext )
                                                                    ->in( $source_dir );
    *blooper* Output header info
    logmsg "==================================";
    logmsg "dMC recursive directory conversion";
    logmsg "==================================";
    @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
    @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
    my $starttime = time();
    ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime($starttime);
    $year = 1900 + $yearOffset;
    $hour = sprintf("%02d", $hour);
    $minute = sprintf("%02d", $minute);
    $second = sprintf("%02d", $second);
    $theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";
    logmsg "Starting conversion at $theTime";
    my $src_backslashed = $source_dir;
    my $dst_backslashed = $dest_dir;
    $src_backslashed =~ s/\//\\/g;
    $dst_backslashed =~ s/\//\\/g;
    logmsg "Source directory: ".$src_backslashed;
    logmsg "Target directory: ".$dst_backslashed;
    logmsg "Converting all ".uc($source_ext)." files to ".$dest_codec;
    logmsg "Codec CLI options: ".$codec_options;
    logmsg "DSP effects: ".$dsp_effects;
    logmsg "dBpoweramp options: ".$dmc_options;
    logmsg "------------------ Conversion ------------------";
    *blooper* Set up fork manager for parallel processing and 
    *blooper* define number of processes to spawn for conversion
    *blooper* (set to, e.g., number of CPUs. Use 0 to disable for testing)
    my $pm = new Parallel::ForkManager($number_of_cpus);
    *blooper* Callback for when a conversion child thread finishes
      sub { my ($pid, $exit_code, $ident) = @_;
        $dst = $ident;
        $dst =~ s/$source_dir(.*)\.$source_ext/$dest_dir$1\.$dest_ext/i;
        my $info = get_mp4info($dst);   *blooper* if converting to MP4, this will allow the encoding speed vs real-time to be calculated
        $total_audio_time += $info->{SECS};
        $ident =~ s/$source_dir\/(.*)\.$source_ext/$1\.$dest_ext/;
        $ident =~ s/\//\\/g;
        *blooper*logmsg "    ...Finished $ident";
    *blooper* Callback for when a conversion child thread is initiated
      sub { my ($pid,$ident)=@_;
        $ident =~ s/$source_dir\///;
        $ident =~ s/\//\\/g;
        logmsg "Converting $ident...";
    *blooper* Process files
    $total_audio_time = 0;
    $total_converted_files = 0;
    foreach my $srcfile (@srcfiles) {
      my $destfile = $srcfile;
      $destfile =~ s/$source_dir(.*)\.$source_ext/$dest_dir$1\.$dest_ext/i;
      *blooper* if the destination file doesn't exist, or the source file is newer, convert!
      if ( ! -e $destfile || get_item_mtime($srcfile) > get_item_mtime($destfile) ) {
        $pm->start($srcfile) and next; *blooper* do the fork 
          $srcfile =~ s/\//\\/g;
          $destfile =~ s/\//\\/g;
          system('"'.$coreconverter_exe.'"' .
                  ' -infile="' . $srcfile . '" ' .
                  ' -outfile="' . $destfile . '" ' .
                  $dmc_options .
                  $dsp_effects .
                  ' -convert_to="' . $dest_codec . '" ' .
        $pm->finish; *blooper* do the exit in the child process
    my $endtime = time();
    ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime($endtime);
    $year = 1900 + $yearOffset;
    $hour = sprintf("%02d", $hour);
    $minute = sprintf("%02d", $minute);
    $second = sprintf("%02d", $second);
    $theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";
    $seconds = $endtime - $starttime;
    @parts = gmtime($seconds);
    $duration = sprintf ("%02d:%02d:%02d", @parts[2,1,0]);
    if ($seconds > 0 && $total_audio_time > 0) {
      $realtime = sprintf("%.1f", $total_audio_time / $seconds);
    } else {
      $realtime = 0;
    @parts = gmtime($total_audio_time);
    if ($total_audio_time > 0) {
      $playing_time = sprintf("%dd %dh %dm", @parts[7,2,1]);
    } else {
      $playing_time = 0;
    *blooper* Clean up - delete any orphaned destination files that
    *blooper* have no matching source (e.g. due to renaming/moving).
    logmsg "------------------- Clean up -------------------";
    my @destfiles = File::Find::Rule->file()
                                                                        ->name( '*.' . $dest_ext )
                                                                        ->in( $dest_dir );
    foreach my $destfile (@destfiles) {
        my $srcfile = $destfile;
        $srcfile =~ s/$dest_dir(.*)\.$dest_ext/$source_dir$1\.$source_ext/i;
        *blooper* If the corresponding source file doesn't exist, delete the destination file
        if ( ! -e $srcfile ) {
            logmsg "Deleted $destfile";
    *blooper* Delete any directories that are now empty
    *blooper* Print some information about how long the encode took before finishing.
    logmsg "------------------ Statistics ------------------";
    logmsg "Finished converting at $theTime.";
    logmsg "Converted $total_converted_files files (total playing time $playing_time).";
    logmsg "Conversion completed in $duration at ${realtime}x real-time encoding speed.\n";
    *blooper* Close the logfile (if it was open)
    close LOGFILE;
    *blooper* Send a Growl message with the stats on completion.
    system("\"C:\\Program Files\\Growl for Windows\\growlnotify.exe\" /t:\"Finished converting\" /i:\"C:\\Program Files\\Illustrate\\dBpoweramp\\CDGrab.png\" /a:ConvertMusic /r:\"Finished Converting\"  /n:\"Finished Converting\" /s:true /silent:true \"$result\"Converted $total_converted_files files (total playing time $playing_time) in $duration (${realtime}x real-time encoding speed).");
    P.S. Because the forum changes all hash marks to '*blooper*', you'll have to change these back to hashes (i.e. comments in Perl).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts