title
Products            Buy            Support Forum            Professional            About            Codec Central
 

Keeping libraries in sync

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rudolffischer
    • Mar 2009
    • 24

    Keeping libraries in sync

    Hi,
    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
    Rudi
  • Teknojnky
    dBpoweramp Guru
    • Dec 2006
    • 323

    #2
    Re: Keeping libraries in sync

    nope.


    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, 09:01 PM.

    Comment

    • Spoon
      Administrator
      • Apr 2002
      • 43898

      #3
      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.
      Spoon
      www.dbpoweramp.com

      Comment

      • rudolffischer
        • Mar 2009
        • 24

        #4
        Re: Keeping libraries in sync

        Thanks to both of you. Will try both suggestions.

        Comment

        • Teknojnky
          dBpoweramp Guru
          • Dec 2006
          • 323

          #5
          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.

          Comment

          • jholvoet
            • Dec 2010
            • 7

            #6
            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, 09:27 PM.

            Comment

            • iangrant
              dBpoweramp Enthusiast
              • Nov 2007
              • 94

              #7
              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.

              Code:
              use File::Find::Rule;
              use File::Find;
              use File::StatCache qw( get_item_mtime );
              use Parallel::ForkManager;
              use MP4::Info;
              
              *blooper*
              *blooper*   Configuration options
              *blooper*   =====================
              *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*
              *blooper* There should be no need to edit anything below this line
              *blooper* ========================================================
              *blooper*
              *blooper*
              
              *blooper*
              *blooper* Logging sub-routine
              *blooper*
              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*
              *blooper* Find all source files
              *blooper*
              my @srcfiles = File::Find::Rule->file()
                                                                              ->name( '*.' . $source_ext )
                                                                              ->in( $source_dir );
              
              
              *blooper*
              *blooper* Output header info
              *blooper*
              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*
              *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)
              *blooper*
              my $pm = new Parallel::ForkManager($number_of_cpus);
              
              *blooper* Callback for when a conversion child thread finishes
              $pm->run_on_finish(
                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};
                  $total_converted_files++;
                  $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
              $pm->run_on_start(
                sub { my ($pid,$ident)=@_;
                  $ident =~ s/$source_dir\///;
                  $ident =~ s/\//\\/g;
                  logmsg "Converting $ident...";
                }
              );
              
              
              *blooper*
              *blooper* Process files
              *blooper*
              $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 . '" ' .
                            $codec_options);
                  $pm->finish; *blooper* do the exit in the child process
                }
              }
              
              $pm->wait_all_children;
              
              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*
              *blooper* Clean up - delete any orphaned destination files that
              *blooper* have no matching source (e.g. due to renaming/moving).
              *blooper*
              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 ) {
                      unlink($destfile);
                      logmsg "Deleted $destfile";
                  }
              }
              *blooper* Delete any directories that are now empty
              finddepth(sub{rmdir},"$dest_dir");
              
              *blooper*
              *blooper* Print some information about how long the encode took before finishing.
              *blooper*
              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*
              *blooper* Send a Growl message with the stats on completion.
              *blooper*
              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).

              Comment

              Working...

              ]]>