私的AI研究会 >MyLibrary2
適宜再利用できそうなプログラムをライブラリ化する その2
「matplotlib.animation」を利用して動画編集をする
機能 | 戻り値 | 関数 |
静止画のリサイズ | image | image_resize(image, size=(256, 256)) |
動画のリサイズ | video | video_resize(video, size=(256, 256)) |
静止画 と 動画 2枚 の連結 | animation | img_movie3x1(image, video, video2=None, interval=30, deley=0, pixel_size=(256,256), dpi=64) |
3枚の動画フレームを連結 | animation | merge3x1_ex(listpath, interval=30, deley=0, pixel_size=(256,256), dpi=64): |
merge3x1(source, interval=30, deley=0, pixel_size=(256,256), dpi=64) | ||
4枚の動画フレームを連結 | animation | merge2x2(source, interval=30, deley=0, pixel_size=(256,256), dpi=64) |
merge2x2_ex(listpath, interval=30, deley=0, pixel_size=(256,256), dpi=64) | ||
6枚の動画フレームを連結 | animation | merge3x2_ex(listpath, interval=30, deley=0, pixel_size=(256,256), dpi=64) |
merge3x2(source, interval=30, deley=0, pixel_size=(256,256), dpi=64) | ||
結果動画の表示と保存(終了処理) | - | save_video(ani, save_path, dispf=False) |
動画ファイルを読み出す | video, fps | read_video(filepath)) |
音声トラックを追加 | - | add_audio(source_path, save_path) |
リストファイルの読み込み | filelist | read_listfile(filepath) |
パラメータ | テスト内容 |
0 | 静止画 と 動画 2枚 の連結 |
1 | 6枚の動画フレームを連結(規定値) |
2 | 4枚の動画フレームを連結(規定値) |
3 | 3枚の動画フレームを連結(規定値) |
4 | 音声トラックを追加 |
5 | リストファイルの読み込み |
10 | リストファイルから 6枚の動画フレームを連結 |
20 | リストファイルから 4枚の動画フレームを連結 |
30 | リストファイルから 3枚の動画フレームを連結 |
40 | 音声トラックを追加 |
$ python my_videotool.py <option:0/1/2/3/4/5> $ python my_videotool.py <option:10/20/30/40> <listfile> <savefile>
# -*- coding: utf-8 -*- ##------------------------------------------ ## My Library Video Tool Ver 0.01 ## 「matplotlib」を利用した動画編集 ## ## 2024.06.14 Masahiro Izutsu ##------------------------------------------ ## my_videotool.py # Color Escape Code GREEN = '\033[1;32m' RED = '\033[1;31m' NOCOLOR = '\033[0m' YELLOW = '\033[1;33m' import imageio.v2 as imageio import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from skimage.transform import resize import ffmpeg import tempfile from shutil import copyfileobj # 静止画のリサイズ * def image_resize(image, size = (256, 256)): image = resize(image, size)[..., :3] return image # 動画のリサイズ * def video_resize(video, size = (256, 256)): video = [resize(frame, size)[..., :3] for frame in video] return video # 静止画 と 動画 2枚 の連結 def img_movie3x1(image, video, video2 = None, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): # ピクセル → インチ変換 x_inch = pixel_size[0] / dpi y_inch = pixel_size[1] / dpi # リサイズ image = image_resize(image, pixel_size) video = video_resize(video, pixel_size) if video2 is not None: video2 = video_resize(video2, pixel_size) fig = plt.figure(figsize = (x_inch * 2 + x_inch * (video2 is not None), y_inch), dpi = dpi) fig.subplots_adjust(left=0, right=1, bottom=0, top=1) ims = [] for i in range(len(video)): cols = [image] cols.append(video[i]) if video2 is not None: cols.append(video2[i]) im = plt.imshow(np.concatenate(cols, axis=1), animated = True) plt.axis('off') ims.append([im]) ani = animation.ArtistAnimation(fig, ims, interval=interval + 3.4) # フレームレート補正 return ani # 3枚の動画フレームを連結 def merge3x1_ex(listpath, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): return merge3x1(read_listfile(listpath)) def merge3x1(source, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): # ピクセル → インチ変換 x_inch = pixel_size[0] / dpi y_inch = pixel_size[1] / dpi result = [] for file_path in source: video = imageio.mimread(file_path, memtest = False) result.append(video_resize(video, pixel_size)) fig = plt.figure(figsize = (x_inch * 3, y_inch), dpi = 64) fig.subplots_adjust(left=0, right=1, bottom=0, top=1) ims =[] for i in range(len(result[0])): x = np.concatenate([result[0][i], result[1][i], result[2][i]],1) z = np.concatenate([x]) im = plt.imshow(z, animated=True) plt.axis('off') ims.append([im]) ani = animation.ArtistAnimation(fig, ims, interval=interval + 3.36) # フレームレート補正 return ani # 4枚の動画フレームを連結 def merge2x2_ex(listpath, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): return merge2x2(read_listfile(listpath)) def merge2x2(source, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): # ピクセル → インチ変換 x_inch = pixel_size[0] / dpi y_inch = pixel_size[1] / dpi result = [] for file_path in source: video = imageio.mimread(file_path, memtest = False) result.append(video_resize(video, pixel_size)) fig = plt.figure(figsize = (x_inch * 2, y_inch * 2), dpi = 64) fig.subplots_adjust(left=0, right=1, bottom=0, top=1) ims =[] for i in range(len(result[0])): x = np.concatenate([result[0][i], result[1][i]],1) y = np.concatenate([result[2][i], result[3][i]],1) z = np.concatenate([x, y]) im = plt.imshow(z, animated=True) plt.axis('off') ims.append([im]) ani = animation.ArtistAnimation(fig, ims, interval=interval + 3.36) # フレームレート補正 return ani # 6枚の動画フレームを連結 def merge3x2_ex(listpath, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): return merge3x2(read_listfile(listpath)) def merge3x2(source, interval = 30, deley = 0, pixel_size = (256,256), dpi = 64): # ピクセル → インチ変換 x_inch = pixel_size[0] / dpi y_inch = pixel_size[1] / dpi result = [] for file_path in source: video = imageio.mimread(file_path, memtest = False) result.append(video_resize(video, pixel_size)) fig = plt.figure(figsize = (x_inch * 3, y_inch * 2), dpi = 64) fig.subplots_adjust(left=0, right=1, bottom=0, top=1) ims =[] for i in range(len(result[0])): x = np.concatenate([result[0][i], result[1][i], result[2][i]],1) y = np.concatenate([result[3][i], result[4][i], result[5][i]],1) z = np.concatenate([x, y]) im = plt.imshow(z, animated=True) plt.axis('off') ims.append([im]) ani = animation.ArtistAnimation(fig, ims, interval=interval + 3.36) # フレームレート補正 return ani # 結果動画の表示と保存(終了処理) def save_video(ani, save_path, dispf = False): if len(save_path) > 0: ani.save(save_path) if dispf: plt.show() plt.close() return # 動画ファイルを読み出す # 戻り値: video... 動画配列 # fps 速度(fps) def read_video(filepath): reader = imageio.get_reader(filepath) fps = reader.get_meta_data()['fps'] video = [] try: for im in reader: video.append(im) except RuntimeError: pass reader.close() return video, fps # 音声トラックを追加 def add_audio(source_path, save_path): try: with tempfile.TemporaryDirectory() as str_temp_dir: tmpfile = f"{str_temp_dir}/temp.mp4" ffmpeg.output(ffmpeg.input(save_path).video, ffmpeg.input(source_path).audio, tmpfile, c='copy').run(quiet=True) with open(save_path, 'wb') as result: with open(tmpfile, 'rb') as output: copyfileobj(output, result) except ffmpeg.Error: print(RED + f"Failed to copy audio: no audio track or the audio format is invalid." + NOCOLOR) # リストファイルの読み込み # 戻り値: filelist... ファイルリスト def read_listfile(filepath): try: f = open(filepath, 'r') list = f.readlines() filelist = [item[:-1] for item in list] except Exception as e: print(RED + f'{e}' + NOCOLOR) filelist = [] return filelist #-----Test routine----- # $ python my_videotool.py <option:0/1/2/3/4/5> # $ python my_videotool.py <option:10/20/30/40> <listfile> <savefile> # if __name__ == "__main__": import os, sys args = sys.argv sel = '0' if len(args) <= 1 else args[1] if sel == '0': # 静止画 と 動画 2枚 の連結 source_list = read_listfile('./mylib_test/filelist.txt') source_image = imageio.imread(source_list[0]) driving_video = imageio.mimread(source_list[1], memtest = False) generated_video = imageio.mimread(source_list[2], memtest = False) ani = img_movie3x1(source_image, driving_video, generated_video) save_video(ani, "test_anim.mp4", True) save_video(ani, "test_anim.gif") elif sel == '1': # 3枚の動画フレームを連結(規定値) ani = merge3x2_ex('./mylib_test/filelist_1.txt') save_video(ani, "test1_anim.mp4", True) save_video(ani, "test1_anim.gif") elif sel == '2': # 4枚の動画フレームを連結(規定値) ani = merge2x2_ex('./mylib_test/filelist_2.txt') save_video(ani, "test2_anim.mp4", True) save_video(ani, "test2_anim.gif") elif sel == '3': # 3枚の動画フレームを連結(規定値) ani = merge3x1_ex('./mylib_test/filelist_3.txt') save_video(ani, "test3_anim.mp4", True) save_video(ani, "test3_anim.gif") elif sel == '4': add_audio('./mylib_test/01_video_256.mp4', './mylib_test/h1_13_out.mp4') elif sel == '5': files = read_listfile('./mylib_test/filelist_1.txt') print(files) else: if len(args) == 4: source_path = args[2] save_path = args[3] print(f" Source file → '{source_path}'") print(f" Saving file → '{save_path}'") if sel == '10': # 6枚の動画フレームを連結 ani = merge3x2_ex(source_path) save_video(ani, save_path, True) elif sel == '20': # 4枚の動画フレームを連結 ani = merge2x2_ex(source_path) save_video(ani, save_path, True) elif sel == '30': # 3枚の動画フレームを連結 ani = merge3x1_ex(source_path) save_video(ani, save_path, True) elif sel == '40': # 音声トラックを追加 add_audio(source_path, save_path)
「opencv」を利用した画像編集
機能 | 関数 |
アスペクト比を固定して画像をリサイズ | frame_resize(image, maxsize) |
画像を正方形にする(長いほうの辺で) | frame_square(image, color = (255, 255, 255)) |
結果の表示と保存(終了処理) | image_disp(image, winname = 'ImageTool', dispf = True, save_path = '') |
画像の種類を判別する(imghdr 非推奨対応) | is_pict(filename) |
イメージを表示 | image2disp(filepath = 'cam', winname = '', savepath = '', width_f = False) |
パラメータ | テスト内容 |
0 | アスペクト比を固定して画像をリサイズ |
1 | 画像を正方形にする(長いほうの辺で) |
2 | 結果の表示と保存(終了処理) |
3 | イメージを表示 |
$ python my_imagetool.py {0/1/...}
# -*- coding: utf-8 -*- ##------------------------------------------ ## My Library Image Tool Ver 0.01 ## ## 2024.06.14 Masahiro Izutsu ##------------------------------------------ ## my_imagetool.py # Color Escape Code GREEN = '\033[1;32m' RED = '\033[1;31m' NOCOLOR = '\033[0m' YELLOW = '\033[1;33m' CYAN = '\033[1;36m' # 定数定義 WINDOW_WIDTH = 640 import os import cv2 import my_winstat import numpy as np # アスペクト比を固定して画像をリサイズ def frame_resize(image, maxsize): if maxsize > 10: img_h, img_w = image.shape[:2] if (img_w > img_h): if (img_w > maxsize): height = round(img_h * (maxsize / img_w)) image = cv2.resize(image, dsize = (maxsize, height)) else: if (img_h > maxsize): width = round(img_w * (maxsize / img_h)) image = cv2.resize(image, dsize = (width, maxsize)) return image # 画像を正方形にする(長いほうの辺で) def frame_square(image, color = (255, 255, 255)): img_h, img_w = image.shape[:2] x0 = 0 y0 = 0 x1 = 0 y1 = 0 if img_h > img_w: size = img_h x0 = int((size - img_w) / 2) x1 = x0 + img_w y1 = size else: size = img_w y0 = int((size - img_h) / 2) y1 = y0 + img_h x1 = size # 白ベースの画像を生成 dist = np.array([size, size, 3]) # 縦×横 3チャンネル img = np.full(dist, color, dtype=np.uint8) img[y0:y1, x0:x1] = image # 中央に貼り付け return img ## 結果の表示と保存(終了処理) def image_disp(image, winname = 'ImageTool', dispf = True, save_path = ''): if len(save_path) > 0: cv2.imwrite(save_path, image) if dispf: cv2.namedWindow(winname, flags = cv2.WINDOW_AUTOSIZE | cv2.WINDOW_GUI_NORMAL) while True: cv2.imshow(winname, image) key = cv2.waitKey(10) if key == 27 or key == 113: # 'esc' or 'q' cv2.destroyWindow(winname) break if not my_winstat._is_visible(winname): break return # 画像の種類を判別する(imghdr 非推奨対応) # 戻り値: 'jeg''png'... 画像ファイル # 'None' 画像ファイル以外 (動画ファイル) # 'NotFound' ファイルが存在しない def is_pict(filename): if not os.path.isfile(filename): return 'NotFound' types = ['.bmp','.png','.jpg','.jpeg','.JPG','.tif'] for ss in types: if filename.endswith(ss): return ss return 'None' # イメージを表示 # filepath: Absolute path to image file or cam/cam0/cam1.. for camera stream. def image2disp(filepath = 'cam', winname = '', savepath = '', width_f = False): if filepath.find('cam') == 0 and len(filepath) < 5: filepath = 0 if filepath == 'cam' else int(filepath[3]) isstream = True else: filetype = is_pict(filepath) isstream = filetype == 'None' if (filetype == 'NotFound'): print(RED + "input file Not found." + NOCOLOR) quit() # 入力準備 if (isstream): # カメラ cap = cv2.VideoCapture(filepath) ret, frame = cap.read() loopflg = cap.isOpened() if not loopflg: print(RED + "Unable to read the camera." + NOCOLOR) else: # 画像ファイル読み込み frame = cv2.imread(filepath) if frame is None: print(RED + "\nUnable to read the input." + NOCOLOR) quit() # アスペクト比を固定してリサイズ img_h, img_w = frame.shape[:2] if width_f and img_w > WINDOW_WIDTH: height = round(img_h * (WINDOW_WIDTH / img_w)) frame = cv2.resize(frame, dsize = (WINDOW_WIDTH, height)) loopflg = True # 1回ループ # 処理結果の記録 step1 if len(savepath) > 0: if isstream: fps = int(cap.get(cv2.CAP_PROP_FPS)) out_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) out_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') outvideo = cv2.VideoWriter(outpath, fourcc, fps, (out_w, out_h)) # メインループ while (loopflg): if frame is None: print(RED + "\nUnable to read the input." + NOCOLOR) quit() # 画像表示 window_name = winname + " (hit 'q' or 'esc' key to exit)" cv2.namedWindow(window_name, flags=cv2.WINDOW_AUTOSIZE | cv2.WINDOW_GUI_NORMAL) cv2.imshow(window_name, frame) # 処理結果の記録 step2 if len(savepath) > 0: if (isstream): outvideo.write(frame) else: cv2.imwrite(outpath, frame) # 何らかのキーが押されたら終了 breakflg = False while(True): key = cv2.waitKey(1) if key == 27 or key == 113: # 'esc' or 'q' breakflg = True cv2.destroyWindow(window_name) break if not my_winstat._is_visible(window_name): # 'Close' button breakflg = True break if (isstream): break if ((breakflg == False) and isstream): # 次のフレームを読み出す ret, frame = cap.read() if ret == False: break loopflg = cap.isOpened() else: loopflg = False # 終了処理 if (isstream): cap.release() # 処理結果の記録 step3 if len(savepath) > 0: if (isstream): outvideo.release() return #-----Test routine----- # $ python my_imagetool.py {option:0/1/2/3...} # if __name__ == "__main__": import os, sys import my_dialog args = sys.argv sel = '0' if len(args) <= 1 else args[1] filename = my_dialog.select_image_file() if sel == '0' or sel == '1' else '' if len(filename) > 0: root, ext = os.path.splitext(filename) print(root) print(ext) savename = root + '_out' + ext base_dir_pair = os.path.split(savename) savename = './' + base_dir_pair[1] print(f'{filename} → {savename}') # frame_resize() if sel == '0': img = cv2.imread(filename) img = frame_resize(img, 256) winname = 'ImageTool frame_resize()' image_disp(img, winname, True, savename) # frame_square() elif sel == '1': img = cv2.imread(filename) img = frame_square(img) winname = 'ImageTool frame_square()' image_disp(img, winname, True, savename) elif sel == '2': filepath = 'mylib_test/04.jpg' img = cv2.imread(filepath) winname = 'ImageTool image_disp()' image_disp(img, winname) elif sel == '3': # filepath = 'mylib_test/04.jpg' filepath = 'cam0' winname = 'ImageTool image_disp()' image2disp(filepath, winname) cv2.destroyAllWindows()
ffmpeg -i "fashion01.mp4" -vf "yadif=deint=interlaced, scale=w=trunc(ih*dar/2)*2:h=trunc(ih/2)*2, setsar=1/1, scale=w=940:h=940:force_original_aspect_ratio=1, pad=w=940:h=940:x=(ow-iw)/2:y=(oh-ih)/2:color=#ffffff" -pix_fmt yuv420p "fashion01_out.mp4"
(py38_learn) ffmpeg -i "fashion01.mp4" -vf "yadif=deint=interlaced, scale=w=trunc(ih*dar/2)*2:h=trunc(ih/2)*2, setsar=1/1, scale=w=940:h=940:force_original_aspect_ratio=1, pad=w=940:h=940:x=(ow-iw)/2:y=(oh-ih)/2:color=#ffffff" -pix_fmt yuv420p "fashion01_out.mp4" ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.2.1 (GCC) 20200122 configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt 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 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'fashion01.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf57.71.100 Duration: 00:00:13.18, start: 0.000000, bitrate: 666 kb/s Stream #0:0(eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 720x940 [SAR 1:1 DAR 36:47], 664 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default) Metadata: handler_name : VideoHandler Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) Press [q] to stop, [?] for help [libx264 @ 0000018ed6367bc0] using SAR=1/1 [libx264 @ 0000018ed6367bc0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0000018ed6367bc0] profile High, level 3.1, 4:2:0, 8-bit [libx264 @ 0000018ed6367bc0] 264 - core 159 - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=29 lookahead_threads=4 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to 'fashion01_out.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.29.100 Stream #0:0(eng): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 940x940 [SAR 1:1 DAR 1:1], q=-1--1, 29.97 fps, 30k tbn, 29.97 tbc (default) Metadata: handler_name : VideoHandler encoder : Lavc58.54.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1 frame= 395 fps=0.0 q=-1.0 Lsize= 1403kB time=00:00:13.07 bitrate= 878.5kbits/s speed=26.9x video:1397kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.390577% [libx264 @ 0000018ed6367bc0] frame I:2 Avg QP:18.76 size: 23849 [libx264 @ 0000018ed6367bc0] frame P:101 Avg QP:23.73 size: 8531 [libx264 @ 0000018ed6367bc0] frame B:292 Avg QP:27.30 size: 1783 [libx264 @ 0000018ed6367bc0] consecutive B-frames: 1.0% 0.5% 2.3% 96.2% [libx264 @ 0000018ed6367bc0] mb I I16..4: 13.2% 74.8% 11.9% [libx264 @ 0000018ed6367bc0] mb P I16..4: 0.3% 1.6% 0.8% P16..4: 6.4% 5.0% 3.0% 0.0% 0.0% skip:82.9% [libx264 @ 0000018ed6367bc0] mb B I16..4: 0.0% 0.0% 0.0% B16..8: 9.6% 2.7% 0.7% direct: 0.4% skip:86.6% L0:45.2% L1:42.0% BI:12.9% [libx264 @ 0000018ed6367bc0] 8x8 transform intra:65.6% inter:45.9% [libx264 @ 0000018ed6367bc0] coded y,uvDC,uvAC intra: 40.9% 33.8% 13.0% inter: 3.4% 1.6% 0.0% [libx264 @ 0000018ed6367bc0] i16 v,h,dc,p: 87% 5% 2% 7% [libx264 @ 0000018ed6367bc0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 39% 5% 38% 2% 3% 4% 2% 4% 3% [libx264 @ 0000018ed6367bc0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 33% 10% 20% 5% 6% 9% 5% 7% 5% [libx264 @ 0000018ed6367bc0] i8c dc,h,v,p: 68% 7% 22% 3% [libx264 @ 0000018ed6367bc0] Weighted P-Frames: Y:0.0% UV:0.0% [libx264 @ 0000018ed6367bc0] ref P L0: 70.8% 12.6% 13.4% 3.2% [libx264 @ 0000018ed6367bc0] ref B L0: 95.1% 4.3% 0.6% [libx264 @ 0000018ed6367bc0] ref B L1: 98.0% 2.0% [libx264 @ 0000018ed6367bc0] kb/s:868.01
ffmpeg -i 01.mp4 -ss 00:00:00.00 -t 00:00:03 -filter:v "crop=340:340:450:80" -async 1 01_video_340.mp4
(py38_learn) ffmpeg -i 01.mp4 -ss 00:00:00.00 -t 00:00:03 -filter:v "crop=340:340:450:80" -async 1 01_video_340.mp4 ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.2.1 (GCC) 20200122 configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt 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 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '01.mp4': Metadata: major_brand : mp42 minor_version : 1 compatible_brands: isommp41mp42 creation_time : 2022-01-28T13:08:43.000000Z Duration: 00:00:02.94, start: 0.000000, bitrate: 945 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 796 kb/s, 29.84 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default) Metadata: creation_time : 2022-01-28T13:08:43.000000Z handler_name : Core Media Video Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default) Metadata: creation_time : 2022-01-28T13:08:43.000000Z handler_name : Core Media Audio Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) Stream #0:1 -> #0:1 (aac (native) -> aac (native)) Press [q] to stop, [?] for help -async is forwarded to lavfi similarly to -af aresample=async=1:min_hard_comp=0.100000:first_pts=0. [libx264 @ 0000018188207ac0] using SAR=1/1 [libx264 @ 0000018188207ac0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 0000018188207ac0] profile High, level 2.1, 4:2:0, 8-bit [libx264 @ 0000018188207ac0] 264 - core 159 - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=11 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to '01_video_340.mp4': Metadata: major_brand : mp42 minor_version : 1 compatible_brands: isommp41mp42 encoder : Lavf58.29.100 Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 340x340 [SAR 1:1 DAR 1:1], q=-1--1, 29.97 fps, 30k tbn, 29.97 tbc (default) Metadata: creation_time : 2022-01-28T13:08:43.000000Z handler_name : Core Media Video encoder : Lavc58.54.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1 Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: creation_time : 2022-01-28T13:08:43.000000Z handler_name : Core Media Audio encoder : Lavc58.54.100 aac frame= 88 fps=0.0 q=-1.0 Lsize= 144kB time=00:00:02.94 bitrate= 400.2kbits/s speed=25.9x video:93kB audio:46kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 3.205245% [libx264 @ 0000018188207ac0] frame I:1 Avg QP:21.58 size: 7014 [libx264 @ 0000018188207ac0] frame P:24 Avg QP:22.92 size: 2542 [libx264 @ 0000018188207ac0] frame B:63 Avg QP:26.62 size: 423 [libx264 @ 0000018188207ac0] consecutive B-frames: 1.1% 9.1% 3.4% 86.4% [libx264 @ 0000018188207ac0] mb I I16..4: 13.2% 72.1% 14.7% [libx264 @ 0000018188207ac0] mb P I16..4: 1.8% 5.9% 0.8% P16..4: 38.3% 17.5% 7.8% 0.0% 0.0% skip:27.8% [libx264 @ 0000018188207ac0] mb B I16..4: 0.1% 0.1% 0.0% B16..8: 36.3% 3.0% 0.3% direct: 0.6% skip:59.6% L0:39.1% L1:53.1% BI: 7.9% [libx264 @ 0000018188207ac0] 8x8 transform intra:69.5% inter:78.6% [libx264 @ 0000018188207ac0] coded y,uvDC,uvAC intra: 48.7% 66.9% 19.8% inter: 9.0% 8.2% 0.2% [libx264 @ 0000018188207ac0] i16 v,h,dc,p: 20% 39% 24% 17% [libx264 @ 0000018188207ac0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 17% 14% 30% 5% 7% 10% 5% 8% 4% [libx264 @ 0000018188207ac0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 34% 11% 12% 6% 11% 10% 5% 8% 3% [libx264 @ 0000018188207ac0] i8c dc,h,v,p: 48% 22% 22% 7% [libx264 @ 0000018188207ac0] Weighted P-Frames: Y:0.0% UV:0.0% [libx264 @ 0000018188207ac0] ref P L0: 65.2% 16.3% 14.3% 4.2% [libx264 @ 0000018188207ac0] ref B L0: 93.4% 5.5% 1.1% [libx264 @ 0000018188207ac0] ref B L1: 97.3% 2.7% [libx264 @ 0000018188207ac0] kb/s:257.87 [aac @ 0000018188276440] Qavg: 189.911
ffmpeg -i outvideo6_17.mp4 -i hi_audio.mp3 -c:v copy -c:a mp3 -map 0:v:0 -map 1:a:0 outvideo6_17_oudio.mp4
(py38_learn) ffmpeg -i outvideo6_17.mp4 -i hi_audio.mp3 -c:v copy -c:a mp3 -map 0:v:0 -map 1:a:0 outvideo6_17_oudio.mp4 ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.2.1 (GCC) 20200122 configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt 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 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'outvideo6_17.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.76.100 Duration: 00:00:02.90, start: 0.000000, bitrate: 999 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 768x512, 994 kb/s, 30.30 fps, 30.30 tbr, 16k tbn, 60.61 tbc (default) Metadata: handler_name : VideoHandler Input #1, mp3, from 'hi_audio.mp3': Metadata: encoder : Lavf58.76.100 Duration: 00:00:02.95, start: 0.025057, bitrate: 128 kb/s Stream #1:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s Metadata: encoder : Lavc58.13 Stream mapping: Stream #0:0 -> #0:0 (copy) Stream #1:0 -> #0:1 (mp3 (mp3float) -> mp3 (libmp3lame)) Press [q] to stop, [?] for help Output #0, mp4, to 'outvideo6_17_oudio.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.29.100 Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 768x512, q=2-31, 994 kb/s, 30.30 fps, 30.30 tbr, 16k tbn, 16k tbc (default) Metadata: handler_name : VideoHandler Stream #0:1: Audio: mp3 (libmp3lame) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp Metadata: encoder : Lavc58.54.100 libmp3lame [libmp3lame @ 0000025df4091f80] Trying to remove 1152 samples, but the queue is empty frame= 88 fps=0.0 q=-1.0 Lsize= 403kB time=00:00:02.92 bitrate=1127.6kbits/s speed=98.3x video:353kB audio:46kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.002753%
ffmpeg -i 01_video_340.mp4 -s 256:256 -q 2 01_video_256.mp4
(py38_learn) ffmpeg -i 01_video_340.mp4 -s 256:256 -q 2 01_video_256.mp4 ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.2.1 (GCC) 20200122 configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt 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 libswscale 5. 5.100 / 5. 5.100 libswresample 3. 5.100 / 3. 5.100 libpostproc 55. 5.100 / 55. 5.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '01_video_340.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.29.100 Duration: 00:00:02.97, start: 0.000000, bitrate: 396 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 340x340 [SAR 1:1 DAR 1:1], 259 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default) Metadata: handler_name : Core Media Video Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: handler_name : Core Media Audio Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) Stream #0:1 -> #0:1 (aac (native) -> aac (native)) Press [q] to stop, [?] for help [libx264 @ 00000266fd448740] -qscale is ignored, -crf is recommended. [libx264 @ 00000266fd448740] using SAR=1/1 [libx264 @ 00000266fd448740] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2 [libx264 @ 00000266fd448740] profile High, level 1.3, 4:2:0, 8-bit [libx264 @ 00000266fd448740] 264 - core 159 - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=8 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to '01_video_256.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.29.100 Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 256x256 [SAR 1:1 DAR 1:1], q=-1--1, 29.97 fps, 30k tbn, 29.97 tbc (default) Metadata: handler_name : Core Media Video encoder : Lavc58.54.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1 Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: handler_name : Core Media Audio encoder : Lavc58.54.100 aac frame= 88 fps=0.0 q=-1.0 Lsize= 122kB time=00:00:02.94 bitrate= 339.8kbits/s speed= 40x video:56kB audio:62kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 3.780259% [libx264 @ 00000266fd448740] frame I:1 Avg QP:21.81 size: 4763 [libx264 @ 00000266fd448740] frame P:27 Avg QP:23.32 size: 1479 [libx264 @ 00000266fd448740] frame B:60 Avg QP:25.73 size: 203 [libx264 @ 00000266fd448740] consecutive B-frames: 2.3% 18.2% 6.8% 72.7% [libx264 @ 00000266fd448740] mb I I16..4: 18.8% 68.8% 12.5% [libx264 @ 00000266fd448740] mb P I16..4: 1.1% 2.3% 0.4% P16..4: 37.9% 24.7% 11.1% 0.0% 0.0% skip:22.5% [libx264 @ 00000266fd448740] mb B I16..4: 0.0% 0.1% 0.0% B16..8: 35.2% 3.7% 0.3% direct: 0.3% skip:60.5% L0:36.0% L1:55.3% BI: 8.7% [libx264 @ 00000266fd448740] 8x8 transform intra:64.7% inter:72.3% [libx264 @ 00000266fd448740] coded y,uvDC,uvAC intra: 51.0% 72.2% 30.2% inter: 10.0% 8.9% 0.3% [libx264 @ 00000266fd448740] i16 v,h,dc,p: 23% 35% 18% 24% [libx264 @ 00000266fd448740] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 13% 12% 27% 6% 9% 12% 6% 11% 5% [libx264 @ 00000266fd448740] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 20% 20% 10% 9% 11% 10% 8% 6% 5% [libx264 @ 00000266fd448740] i8c dc,h,v,p: 56% 20% 18% 6% [libx264 @ 00000266fd448740] Weighted P-Frames: Y:0.0% UV:0.0% [libx264 @ 00000266fd448740] ref P L0: 66.0% 16.2% 13.3% 4.5% [libx264 @ 00000266fd448740] ref B L0: 94.6% 4.8% 0.6% [libx264 @ 00000266fd448740] ref B L1: 98.0% 2.0% [libx264 @ 00000266fd448740] kb/s:155.03 [aac @ 00000266ff1fdcc0] Qavg: 236.000
(py38_gan) PS > pip install yt-dlp
# YouTube ダウンロード # 2023.11.18 # ytb_down.py # ffmpeg yt-dlp # test: opt = ['https://www.youtube.com/watch?v=7G0ovtPqHnI'] # # 【簡単便利】pythonからYouTubeを高画質でdownloadするぞ!by Windows # https://resanaplaza.com/2023/04/02/%E3%80%90%E7%B0%A1%E5%8D%98%E4%BE%BF%E5%88%A9%E3%80%91python%E3%81%8B%E3%82%89youtube%E3%82%92%E9%AB%98%E7%94%BB%E8%B3%AA%E3%81%A7download%E3%81%99%E3%82%8B%E3%81%9E%EF%BC%81by-windows/ from yt_dlp import YoutubeDL def ytb_download(option): ydl = YoutubeDL() result = ydl.download(option) return result if __name__ == "__main__": import sys opt = [] args = sys.argv for n in range(len(args)): print(n, args[n]) if n >= 1: opt.append(args[n]) if len(opt) == 0: print('Please input potion parameter !!') print(opt) result = ytb_download(opt)
python ytb_down.py 'https://youtu.be/cZM3o5KWLKQ'
(py38_learn) python ytb_down.py 'https://youtu.be/cZM3o5KWLKQ' 0 ytb_down.py 1 https://youtu.be/cZM3o5KWLKQ ['https://youtu.be/cZM3o5KWLKQ'] [youtube] Extracting URL: https://youtu.be/cZM3o5KWLKQ [youtube] cZM3o5KWLKQ: Downloading webpage [youtube] cZM3o5KWLKQ: Downloading ios player API JSON [youtube] cZM3o5KWLKQ: Downloading android player API JSON WARNING: [youtube] YouTube said: ERROR - Precondition check failed. WARNING: [youtube] HTTP Error 400: Bad Request. Retrying (1/3)... [youtube] cZM3o5KWLKQ: Downloading android player API JSON WARNING: [youtube] YouTube said: ERROR - Precondition check failed. WARNING: [youtube] HTTP Error 400: Bad Request. Retrying (2/3)... [youtube] cZM3o5KWLKQ: Downloading android player API JSON WARNING: [youtube] YouTube said: ERROR - Precondition check failed. WARNING: [youtube] HTTP Error 400: Bad Request. Retrying (3/3)... [youtube] cZM3o5KWLKQ: Downloading android player API JSON WARNING: [youtube] YouTube said: ERROR - Precondition check failed. WARNING: [youtube] Unable to download API page: HTTP Error 400: Bad Request (caused by <HTTPError 400: Bad Request>); please report this issue on https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using yt-dlp -U [youtube] cZM3o5KWLKQ: Downloading m3u8 information [info] cZM3o5KWLKQ: Downloading 1 format(s): 248+251 [download] Destination: 花王 セグレタ 「肌のように、髪を愛そう。」篇 30秒 CM 柴咲コウ [cZM3o5KWLKQ].f248.webm [download] 100% of 4.96MiB in 00:00:00 at 34.11MiB/s [download] Destination: 花王 セグレタ 「肌のように、髪を愛そう。」篇 30秒 CM 柴咲コウ [cZM3o5KWLKQ].f251.webm [download] 100% of 495.41KiB in 00:00:00 at 10.58MiB/s [Merger] Merging formats into "花王 セグレタ 「肌のように、髪を愛そう。」篇 30秒 CM 柴咲コウ [cZM3o5KWLKQ].webm" Deleting original file 花王 セグレタ 「肌のように、髪を愛そう。」篇 30秒 CM 柴咲コウ [cZM3o5KWLKQ].f251.webm (pass -k to keep) Deleting original file 花王 セグレタ 「肌のように、髪を愛そう。」篇 30秒 CM 柴咲コウ [cZM3o5KWLKQ].f248.webm (pass -k to keep)
PukiWiki 1.5.2 © 2001-2019 PukiWiki Development Team. Powered by PHP 7.4.3-4ubuntu2.24. HTML convert time: 0.070 sec.