Пример #1
0
def main():
    """jwb-offline

    Video player script
    """
    def handler(signal, frame):
        raise KeyboardInterrupt

    signal.signal(signal.SIGTERM, handler)

    parser = argparse.ArgumentParser(
        prog='jwb-offline',
        usage='%(prog)s [DIR] [COMMAND]',
        description='Shuffle and play videos in DIR')
    parser.add_argument('dir', nargs='?', metavar='DIR', default='.')
    parser.add_argument(
        'cmd',
        nargs='+',
        metavar='COMMAND',
        help=
        'video player command, "{}" gets replaced by starting position in secs'
    )
    parser.add_argument('--replay-sec',
                        metavar='SEC',
                        type=int,
                        default=30,
                        dest='replay',
                        help='seconds to replay after a restart')
    parser.add_argument('--verbose',
                        action='store_true',
                        help='show video player output')

    args = parser.parse_args()
    args.dir = Path(args.dir)

    m = VideoManager(args.dir,
                     replay=args.replay,
                     cmd=args.cmd,
                     verbose=args.verbose)

    try:
        m.read_dump()
    except json.JSONDecodeError:
        pass

    showmsg = True
    try:
        while True:
            if m.set_random_video():
                m.play_video()
                showmsg = True
            else:
                if showmsg:
                    msg('no videos to play yet')
                    showmsg = False
                time.sleep(10)
                continue
    except KeyboardInterrupt:
        msg('aborted')
        m.write_dump()
Пример #2
0
    def play_video(self):
        """Play a video"""
        self.write_dump()
        msg('playing: ' + self.video.name)
        cmd = [arg.replace('{}', str(self.pos))
               for arg in self.cmd] + [str(self.video)]
        self.start_time = time.time()
        if self.verbose:
            subprocess.call(cmd)
        else:
            subprocess.call(cmd,
                            stdout=subprocess.DEVNULL,
                            stderr=subprocess.DEVNULL)

        if self.calculate_pos() == 0:
            self.errors = self.errors + 1
        else:
            self.errors = 0
        if self.errors > 10:
            raise RuntimeError('video player restarting too quickly')

        self.add_to_history(self.video)
        self.video = None
Пример #3
0
def main():
    usage = '''
      %(prog)s [options] [DIR]
      %(prog)s [options] --mode=html|m3u|txt [FILE]
      %(prog)s [options] --mode=run COMMAND [ARGS]'''

    p = argparse.ArgumentParser(
        prog='jwb-index',
        usage=usage,
        description='Index or download media from jw.org',
        argument_default=argparse.SUPPRESS
    )  # Do not overwrite attributes with None

    p.add_argument('--append',
                   action='store_true',
                   help='append to file instead of overwriting')
    p.add_argument('--category',
                   '-c',
                   dest='include_categories',
                   metavar='CODE',
                   action=action_factory(lambda x: x.split(',')),
                   help='comma separated list of categories to index')
    p.add_argument('--checksum',
                   action='store_true',
                   dest='checksums',
                   help="validate MD5 checksums")
    p.add_argument('--clean-symlinks',
                   action='store_true',
                   dest='clean_all_symlinks',
                   help='remove all old symlinks (mode=filesystem)')
    p.add_argument('--download',
                   '-d',
                   action='store_true',
                   help='download media files')
    p.add_argument('--download-subtitles',
                   action='store_true',
                   help='download VTT subtitle files')
    p.add_argument(
        '--exclude',
        metavar='CODE',
        dest='exclude_categories',
        action=action_factory(lambda x: x.split(',')),
        help=
        'comma separated list of categories to skip (sub-categories will also be skipped)'
    )
    p.add_argument(
        '--fix-broken',
        action='store_true',
        dest='overwrite_bad',
        help='check existing files and re-download them if they are broken')
    p.add_argument(
        '--free',
        type=int,
        metavar='MiB',
        dest='keep_free',
        action=action_factory(lambda x: x * 1024 * 1024),  # MiB to B
        help=
        'disk space in MiB to keep free (warning: deletes old MP4 files, use separate folder!)'
    )
    p.add_argument('--friendly',
                   '-H',
                   action='store_true',
                   dest='friendly_filenames',
                   help='save downloads with human readable names')
    p.add_argument('--hard-subtitles',
                   action='store_true',
                   help='prefer videos with hard-coded subtitles')
    p.add_argument('--import',
                   dest='import_dir',
                   metavar='DIR',
                   help='import of media files from this directory (offline)')
    p.add_argument('--lang',
                   '-l',
                   action=action_factory(verify_language),
                   help='language code')
    p.add_argument('--languages',
                   '-L',
                   nargs=0,
                   action=action_factory(print_language),
                   help='display a list of valid language codes')
    p.add_argument('--latest',
                   action='store_true',
                   help='index the "Latest Videos" category only')
    p.add_argument(
        '--limit-rate',
        '-R',
        metavar='RATE',
        type=float,
        dest='rate_limit',
        help=
        'maximum download rate, in megabytes/s (default = 1 MB/s, 0 = no limit)'
    )
    p.add_argument('--list-categories',
                   '-C',
                   nargs='?',
                   const='VideoOnDemand',
                   metavar='CODE',
                   dest='print_category',
                   help='print a list of (sub) category names')
    p.add_argument('--mode',
                   '-m',
                   choices=[
                       'filesystem', 'html', 'html_tree', 'm3u', 'm3u_multi',
                       'm3u_tree', 'run', 'stdout', 'txt'
                   ],
                   help='output mode (see wiki)')
    p.add_argument('--no-warning',
                   dest='warning',
                   action='store_false',
                   help='do not warn when space limit seems wrong')
    p.add_argument('--quality',
                   '-Q',
                   type=int,
                   choices=[240, 360, 480, 720],
                   help='maximum video quality')
    p.add_argument('--quiet',
                   '-q',
                   action='count',
                   help='Less info, can be used multiple times')
    p.add_argument('--since',
                   metavar='YYYY-MM-DD',
                   dest='min_date',
                   action=action_factory(
                       lambda x: time.mktime(time.strptime(x, '%Y-%m-%d'))),
                   help='only index media newer than this date')
    p.add_argument('--sort',
                   choices=['newest', 'oldest', 'name', 'random'],
                   help='sort output')
    p.add_argument(
        '--update',
        action='store_true',
        help=
        'update existing categories with the latest videos (implies --append --latest --sort=newest)'
    )
    p.add_argument('positional_arguments',
                   nargs='*',
                   metavar='DIR|FILE|COMMAND',
                   help='where to send output (depends on mode)')

    s = p.parse_args(namespace=Settings())

    # Quick print of categories list
    if s.print_category:
        print(*get_categories(s, s.print_category), sep='\n')
        exit()

    # Required arguments
    if not (s.mode or s.download or s.download_subtitles or s.import_dir):
        msg('please use --mode or --download')
        exit(1)

    # Implicit arguments
    if s.update:
        s.append = True
        s.latest = True
        if not s.sort:
            s.sort = 'newest'
    if s.latest:
        for key in s.include_categories:
            if key != 'VideoOnDemand':
                # Add key and its sub categories to the filter
                s.filter_categories.append(key)
                if s.quiet < 1:
                    msg('preparing filter: ' + key)
                s.filter_categories += get_categories(s, key)
        s.include_categories = ['LatestVideos']

    # Handle positional arguments depending on mode
    # COMMAND [ARGS]
    if s.mode == 'run':
        if not s.positional_arguments:
            msg('--mode=run requires a command')
            exit(1)
        s.command = s.positional_arguments

    elif len(s.positional_arguments) == 1:
        path = Path(s.positional_arguments[0])
        # FILE
        if s.mode in ('txt', 'm3u', 'html') and not path.is_dir():
            s.output_filename = path.name
            s.work_dir = path.parent
        # DIR
        else:
            s.work_dir = path

    elif len(s.positional_arguments) > 1:
        msg('unexpected argument: {}'.format(s.positional_arguments[1]))
        exit(1)

    # Check / set paths
    if not s.work_dir.is_dir():
        msg('not a directory: ' + str(s.work_dir))
        exit(1)

    if s.mode not in ('', 'stdout'):
        s.sub_dir = 'jwb-' + s.lang

    # Warning if disk space is already below limit
    if (s.download or s.import_dir) and s.keep_free > 0:
        disk_usage_info(s)

    # Offline import (stops here)
    if s.import_dir:
        copy_files(s)
        exit()

    # NTFS compatibility (try to create a forbidden file)
    try:
        (s.work_dir / '?').touch(exist_ok=False)
        (s.work_dir / '?').unlink()
    except FileExistsError:
        pass
    except OSError:
        s.safe_filenames = True

    # Some heads-up
    if s.quiet < 1:
        if s.download and s.rate_limit:
            msg('note: download rate limit is active')
        if s.safe_filenames:
            msg('note: using NTFS/FAT compatible file names')

    # Do the indexing
    data = parse_broadcasting(s)

    if s.download or s.download_subtitles:
        download_all(s, data)

    if s.mode:
        create_output(s, data)
Пример #4
0
def print_language(x):
    msg('language codes:')
    for l in get_jwb_languages():
        msg('{:>3}  {:<}'.format(l['code'], l['name']))
    exit()