{"id":1669,"date":"2025-10-10T07:17:38","date_gmt":"2025-10-09T22:17:38","guid":{"rendered":"https:\/\/beeknowledge.co.jp\/?p=1669"},"modified":"2025-10-10T07:17:39","modified_gmt":"2025-10-09T22:17:39","slug":"gopro%e3%81%8b%e3%82%89%e7%b7%af%e5%ba%a6%e7%b5%8c%e5%ba%a6%e6%83%85%e5%a0%b1%e7%ad%89%e3%81%ae%e3%83%a1%e3%82%bf%e6%83%85%e5%a0%b1%e3%81%ae%e5%8f%96%e3%82%8a%e5%87%ba%e3%81%97%e6%96%b9","status":"publish","type":"post","link":"https:\/\/beeknowledge.co.jp\/?p=1669","title":{"rendered":"GoPro\u304b\u3089\u7def\u5ea6\u7d4c\u5ea6\u60c5\u5831\u7b49\u306e\u30e1\u30bf\u60c5\u5831\u306e\u53d6\u308a\u51fa\u3057\u65b9"},"content":{"rendered":"\n<!doctype html>\n<html lang=\"ja\">\n<head>\n<meta charset=\"utf-8\">\n<title>GoPro\u52d5\u753b\u2192GPX\u62bd\u51fa\u30fb1Hz\u6574\u5f62\u30fb720p\u518d\u30a8\u30f3\u30b3\u30fc\u30c9\u30fb\u9032\u6357\u53ef\u8996\u5316\u30fb\u30e1\u30bf\u30c7\u30fc\u30bf\u7d99\u627f\u30c4\u30fc\u30eb\uff08\u30bd\u30fc\u30b9\u4ed8\u304d\uff09<\/title>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<style>\n  :root { --fg:#0a0a0a; --muted:#666; --accent:#0b79d0; --bg:#fff; --card:#f6f7f9; }\n  html,body{background:var(--bg);color:var(--fg);font-family:system-ui,-apple-system,Segoe UI,Roboto,Meiryo,Arial,sans-serif;line-height:1.75;margin:0}\n  header,section{max-width:1100px;margin:auto;padding:28px 20px}\n  h1{font-size:28px;margin:0 0 6px}\n  h2{font-size:22px;margin:28px 0 8px;border-left:6px solid var(--accent);padding-left:10px}\n  h3{font-size:18px;margin:20px 0 8px}\n  p.lead{font-size:16px;color:#222}\n  .grid{display:grid;gap:14px}\n  .cols-2{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}\n  .card{background:var(--card);border-radius:12px;padding:16px}\n  code,kbd,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}\n  pre{background:#0a0a0a;color:#e6e6e6;border-radius:10px;padding:14px;overflow:auto}\n  ul{margin:8px 0 8px 22px}\n  li{margin:6px 0}\n  .muted{color:var(--muted)}\n  .pill{display:inline-block;background:#e8f2fb;color:#0b79d0;padding:2px 8px;border-radius:999px;font-size:12px}\n  .warn{background:#fff3cd;color:#8a6d3b;border-left:4px solid #ffb900;padding:12px;border-radius:8px}\n  .ok{background:#e9f7ef;color:#1e7e34;border-left:4px solid #28a745;padding:12px;border-radius:8px}\n  .kbd{background:#eee;border:1px solid #ddd;border-bottom-width:2px;padding:2px 6px;border-radius:6px}\n  details summary{cursor:pointer;font-weight:700}\n  textarea{width:100%;min-height:520px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.5;border:1px solid #ddd;border-radius:10px;padding:12px;background:#0a0a0a;color:#e6e6e6}\n<\/style>\n<\/head>\n<body>\n\n<header>\n  <h1>\u3053\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u306f\u4f55\u3092\u3059\u308b\uff1f\uff08\u30bd\u30fc\u30b9\u4ed8\u304d\u89e3\u8aac\uff09<\/h1>\n  <p class=\"lead\">\n    GoPro\u306e\u52d5\u753b\u304b\u3089<strong>GPS\u8ecc\u8de1\uff08GPX\uff09<\/strong>\u3092\u629c\u304d\u51fa\u3057\u3001<strong>1\u79d2\u9593\u9694<\/strong>\u306b\u6574\u5f62\u3002\u52d5\u753b\u306f<strong>1280\u00d7720 \/ 6Mbps<\/strong>\u3067\n    QSV\/AMF\/MF \u3044\u305a\u308c\u304b\u306e<strong>\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u30a8\u30f3\u30b3\u30fc\u30c0<\/strong>\u3067\u518d\u30a8\u30f3\u30b3\u30fc\u30c9\u3002<br>\n    \u30a8\u30f3\u30b3\u30fc\u30c9\u9032\u6357\u3092<strong>CSV\/SVG<\/strong>\u3067\u4fdd\u5b58\u3057\u3001\u6700\u5f8c\u306b<strong>ExifTool<\/strong>\u3067\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u5b8c\u6210MP4\u3078<strong>\u4e38\u30b3\u30d4\u30fc<\/strong>\u3057\u307e\u3059\u3002\n  <\/p>\n<\/header>\n\n<section>\n  <h2>\u51e6\u7406\u306e\u5168\u4f53\u50cf<\/h2>\n  <ol>\n    <li><strong>GPX\u30c6\u30f3\u30d7\u30ec\u751f\u6210<\/strong> \u2192 <strong>GPS\u62bd\u51fa<\/strong>\uff08ExifTool\uff09\u3002<\/li>\n    <li><strong>1Hz\u6574\u5f62<\/strong>\uff08\u5404\u79d2\u306e\u5148\u982d\u70b9\u3092\u63a1\u7528\u3001\u901f\u5ea6\/\u9ad8\u5ea6\u306f\u6570\u5024\u62bd\u51fa\uff09\u3002<\/li>\n    <li><strong>example.gpx\u4e92\u63db<\/strong>\u3067GPX\u3092\u66f8\u304d\u51fa\u3057\u3002<\/li>\n    <li><strong>720p\/6Mbps<\/strong>\u3067\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u518d\u30a8\u30f3\u30b3\u30fc\u30c9\uff08libx264\u3078\u306f\u843d\u3068\u3055\u306a\u3044\u65b9\u91dd\uff09\u3002<\/li>\n    <li><strong>\u9032\u6357\u30ed\u30b0<\/strong>\uff08CSV\/SVG\uff09\u3092\u81ea\u52d5\u751f\u6210\u3002<\/li>\n    <li><strong>\u30e1\u30bf\u30c7\u30fc\u30bf<\/strong>\u3092\u5143\u52d5\u753b\u304b\u3089\u65b0MP4\u3078\u30b3\u30d4\u30fc\u3002<\/li>\n  <\/ol>\n<\/section>\n\n<section>\n  <h2>\u4f7f\u3044\u65b9\uff08\u4f8b\uff09<\/h2>\n  <div class=\"card\">\n    <pre>python gopro_gpx_720p.py \"F:\\videos\\gopro_session\" --overwrite --hwenc auto<\/pre>\n    <ul>\n      <li><span class=\"kbd\">path<\/span>\uff1a\u52d5\u753b\u30d5\u30a1\u30a4\u30eb or \u30d5\u30a9\u30eb\u30c0\uff08.mp4\/.mov\/.m4v \u3092\u518d\u5e30\u63a2\u7d22\uff09<\/li>\n      <li><span class=\"kbd\">&#8211;ffmpeg<\/span> \/ <span class=\"kbd\">&#8211;exiftool<\/span>\uff1a\u540c\u68b1\u3057\u306a\u3044\u5834\u5408\u306f\u660e\u793a\u30d1\u30b9\u53ef<\/li>\n      <li><span class=\"kbd\">&#8211;overwrite<\/span>\uff1a\u65e2\u5b58\u306e <code>_1280_720.*<\/code> \u3092\u4e0a\u66f8\u304d<\/li>\n      <li><span class=\"kbd\">&#8211;hwenc<\/span>\uff1a<code>auto<\/code>\/<code>qsv<\/code>\/<code>amf<\/code>\/<code>mf<\/code>\uff08<strong>libx264\u306b\u306f\u843d\u3061\u307e\u305b\u3093<\/strong>\uff09<\/li>\n      <li><span class=\"kbd\">&#8211;no-progress<\/span>\uff1a\u9032\u6357CSV\/SVG\u3092\u4f5c\u3089\u306a\u3044<\/li>\n    <\/ul>\n  <\/div>\n<\/section>\n\n<section>\n  <h2>\u8981\u70b9\u3068\u6ce8\u610f<\/h2>\n  <div class=\"warn\">\n    <strong>\u6ce8\u610f\uff1a<\/strong>\u5f15\u6570\u306b <code>nvenc<\/code> \u306f\u3042\u308a\u307e\u3059\u304c\u3001\u5019\u88dc\u5217\u6319\u306f <code>h264_qsv \/ h264_amf \/ h264_mf<\/code> \u306e\u307f\u3002<br>\n    NVIDIA\u5c02\u7528\u306b\u3057\u305f\u3044\u5834\u5408\u306f <code>pick_encoder_list()<\/code> \u306b <code>h264_nvenc<\/code> \u306e\u30a8\u30f3\u30c8\u30ea\u3092\u8ffd\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n  <\/div>\n<\/section>\n\n<section>\n  <h2>\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\uff08\u5168\u6587\uff09<\/h2>\n  <details open>\n    <summary>\u30af\u30ea\u30c3\u30af\u3067\u6298\u308a\u305f\u305f\u307f\uff0f\u5c55\u958b<\/summary>\n    <textarea readonly>\n#!\/usr\/bin\/env python3\n# -*- coding: utf-8 -*-\n\n&#8220;&#8221;&#8221;\nGoPro \u2192 (1) ExifTool\u30c6\u30f3\u30d7\u30ec\u3067GPX\u5438\u51fa\u3057 \u2192 (2) example.gpx\u4e92\u63db\u306b\u6574\u5f62\uff0b1Hz\u9593\u5f15\u304d\n\u2192 (3) H.264 1280&#215;720 \/ 6Mbps\uff08libx264\u4e0d\u4f7f\u7528\u30fbQSV\u2192AMF\u2192MF\uff09\u2192 (4) \u9032\u6357CSV\/SVG\n\u2192 (5) \u51fa\u529bMP4\u3078\u30e1\u30bf\u30c7\u30fc\u30bf\u4e38\u30b3\u30d4\u30fc\uff08ExifTool -TagsFromFile\uff09\n\n\u51fa\u529b:\n  <\u5143\u540d>_1280_720.gpx\n  <\u5143\u540d>_1280_720.mp4\n  <\u5143\u540d>_1280_720_progress.csv \/ .svg\n\n\u540c\u68b1\u60f3\u5b9a:\n  tools\/ffmpeg\/ffmpeg.exe\n  tools\/exiftool\/exiftool.exe\n&#8220;&#8221;&#8221;\n\nimport argparse\nimport csv\nimport os\nimport re\nimport sys\nimport subprocess\nimport tempfile\nimport time\nfrom pathlib import Path\nfrom typing import Optional, List, Tuple, Dict\nfrom shutil import which as shutil_which\nfrom datetime import datetime\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- \u30e9\u30f3\u30bf\u30a4\u30e0\u88dc\u52a9 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef runtime_base_dir() -> Path:\n    base = os.environ.get(&#8220;NUITKA_ONEFILE_TEMP_DIR&#8221;)\n    if base:\n        return Path(base)\n    if hasattr(sys, &#8220;_MEIPASS&#8221;):\n        return Path(getattr(sys, &#8220;_MEIPASS&#8221;))\n    if getattr(sys, &#8220;frozen&#8221;, False):\n        return Path(sys.executable).resolve().parent\n    return Path(__file__).resolve().parent\n\ndef which(cmd: str) -> Optional[str]:\n    exts = os.environ.get(&#8220;PATHEXT&#8221;, &#8220;.EXE;.BAT;.CMD&#8221;).split(&#8220;;&#8221;)\n    paths = os.environ.get(&#8220;PATH&#8221;, &#8220;&#8221;).split(os.pathsep)\n    p = Path(cmd)\n    if p.exists():\n        return str(p)\n    cand = [cmd] if p.suffix else [cmd + ext for ext in exts] + [cmd]\n    for d in paths:\n        for c in cand:\n            f = Path(d) \/ c\n            if f.exists() and f.is_file():\n                return str(f)\n    return None\n\ndef resolve_tool(name: str, cli_path: Optional[str], bundled_rel: Path) -> str:\n    # 1) CLI\u660e\u793a \u2192 2) \u540c\u68b1 \u2192 3) PATH\n    if cli_path:\n        if Path(cli_path).exists():\n            return str(Path(cli_path))\n        sys.exit(f&#8221;ERROR: {name} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093: {cli_path}&#8221;)\n    base = runtime_base_dir()\n    cand = base \/ bundled_rel\n    if cand.exists():\n        return str(cand)\n    found = which(name)\n    if found:\n        return found\n    sys.exit(\n        f&#8221;ERROR: {name} \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002PATH\u3078\u8ffd\u52a0\u3059\u308b\u304b &#8211;{name} \u3067\u660e\u793a\u3001&#8221;\n        f&#8221;\u307e\u305f\u306f tools\/{name}\/{name}.exe \u3092\u540c\u68b1\u3057\u3066\u304f\u3060\u3055\u3044\u3002&#8221;\n    )\n\ndef resolve_ffprobe_path(ffmpeg_path: str) -> str:\n    # ffmpeg.exe \u3068\u540c\u3058\u30d5\u30a9\u30eb\u30c0\u3092\u6700\u512a\u5148\u3067\u63a2\u3059\n    p = Path(ffmpeg_path)\n    for nm in (&#8220;ffprobe.exe&#8221;, &#8220;ffprobe&#8221;):\n        cand = p.with_name(nm)\n        if cand.exists():\n            return str(cand)\n    w = shutil_which(&#8220;ffprobe&#8221;)\n    if w:\n        return w\n    sys.exit(&#8220;ERROR: ffprobe \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002ffmpeg \u3068\u540c\u68b1\u3059\u308b\u304b PATH \u306b\u901a\u3057\u3066\u304f\u3060\u3055\u3044\u3002&#8221;)\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- \u5171\u901a\u30ed\u30b8\u30c3\u30af &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef is_video(p: Path) -> bool:\n    return p.suffix.lower() in {&#8220;.mp4&#8221;, &#8220;.mov&#8221;, &#8220;.m4v&#8221;}\n\ndef build_gpx_template() -> Path:\n    # \u2605\u3042\u306a\u305f\u306e\u300c\u53d6\u308c\u3066\u3044\u305f\u300d\u30c6\u30f3\u30d7\u30ec\u305d\u306e\u307e\u307e\n    gpx_text = &#8220;&#8221;&#8221;#[HEAD]<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"1.1\" creator=\"ExifTool\"\n xmlns=\"http:\/\/www.topografix.com\/GPX\/1\/1\"\n xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n xsi:schemaLocation=\"http:\/\/www.topografix.com\/GPX\/1\/1\n http:\/\/www.topografix.com\/GPX\/1\/1\/gpx.xsd\">\n<trk><name>$FileName<\/name><trkseg>\n#[BODY]<trkpt lat=\"$GPSLatitude#\" lon=\"$GPSLongitude#\"><time>$GPSDateTime<\/time><ele>$GPSAltitude<\/ele><speed>$GPSSpeed<\/speed><\/trkpt>\n#[TAIL]<\/trkseg><\/trk><\/gpx>\n&#8220;&#8221;&#8221;\n    tmp = tempfile.NamedTemporaryFile(delete=False, suffix=&#8221;.fmt&#8221;, mode=&#8221;w&#8221;, encoding=&#8221;utf-8&#8243;)\n    tmp.write(gpx_text)\n    tmp.close()\n    return Path(tmp.name)\n\ndef ffmpeg_has_encoder(ffmpeg: str, enc: str) -> bool:\n    try:\n        res = subprocess.run([ffmpeg, &#8220;-hide_banner&#8221;, &#8220;-encoders&#8221;], capture_output=True, text=True, check=True)\n        return f&#8221; {enc} &#8221; in res.stdout\n    except Exception:\n        return False\n\ndef pick_encoder_list(ffmpeg: str, forced: str) -> List[Tuple[str, List[str]]]:\n    # 6 Mbps \u56fa\u5b9a\uff08libx264\u306f\u542b\u3081\u306a\u3044\uff09\n    br, maxrate, buf = &#8220;6M&#8221;, &#8220;6M&#8221;, &#8220;12M&#8221;\n\n    if forced == &#8220;qsv&#8221;:\n        return [(&#8220;h264_qsv&#8221;, [&#8220;-c:v&#8221;, &#8220;h264_qsv&#8221;, &#8220;-b:v&#8221;, br, &#8220;-maxrate&#8221;, maxrate, &#8220;-bufsize&#8221;, buf])]\n    if forced == &#8220;amf&#8221;:\n        return [(&#8220;h264_amf&#8221;, [&#8220;-c:v&#8221;, &#8220;h264_amf&#8221;, &#8220;-b:v&#8221;, br, &#8220;-maxrate&#8221;, maxrate, &#8220;-bufsize&#8221;, buf])]\n    if forced == &#8220;mf&#8221;:\n        return [(&#8220;h264_mf&#8221;,  [&#8220;-c:v&#8221;, &#8220;h264_mf&#8221;,  &#8220;-b:v&#8221;, br])]\n\n    cands: List[Tuple[str, List[str]]] = []\n    if ffmpeg_has_encoder(ffmpeg, &#8220;h264_qsv&#8221;):\n        cands.append((&#8220;h264_qsv&#8221;, [&#8220;-c:v&#8221;, &#8220;h264_qsv&#8221;, &#8220;-b:v&#8221;, br, &#8220;-maxrate&#8221;, maxrate, &#8220;-bufsize&#8221;, buf]))\n    if ffmpeg_has_encoder(ffmpeg, &#8220;h264_amf&#8221;):\n        cands.append((&#8220;h264_amf&#8221;, [&#8220;-c:v&#8221;, &#8220;h264_amf&#8221;, &#8220;-b:v&#8221;, br, &#8220;-maxrate&#8221;, maxrate, &#8220;-bufsize&#8221;, buf]))\n    if ffmpeg_has_encoder(ffmpeg, &#8220;h264_mf&#8221;):\n        cands.append((&#8220;h264_mf&#8221;,  [&#8220;-c:v&#8221;, &#8220;h264_mf&#8221;,  &#8220;-b:v&#8221;, br]))\n    return cands\n\ndef build_filters() -> List[str]:\n    # SW\u30b9\u30b1\u30fc\u30eb+pad\u3067\u5e38\u306b 1280&#215;720\uff08\u4e92\u63db\u6027\u306e\u305f\u3081 yuv420p\uff09\n    vf = &#8220;scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)\/2:(oh-ih)\/2&#8221;\n    return [&#8220;-vf&#8221;, vf, &#8220;-pix_fmt&#8221;, &#8220;yuv420p&#8221;]\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- \u9032\u6357\u53d6\u5f97\uff06\u53ef\u8996\u5316 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef _run_ffprobe_val(ffprobe: str, args: List[str]) -> Optional[float]:\n    try:\n        res = subprocess.run([ffprobe] + args, capture_output=True, text=True, check=True)\n        s = res.stdout.strip()\n        if not s:\n            return None\n        val = float(s)\n        if val > 0 and val != float(&#8220;inf&#8221;):\n            return val\n    except Exception:\n        return None\n    return None\n\ndef ffprobe_duration_sec(ffmpeg: str, src: Path) -> Optional[float]:\n    ffprobe = resolve_ffprobe_path(ffmpeg)\n    # 1) format.duration\n    dur = _run_ffprobe_val(ffprobe, [\n        &#8220;-v&#8221;, &#8220;error&#8221;,\n        &#8220;-show_entries&#8221;, &#8220;format=duration&#8221;,\n        &#8220;-of&#8221;, &#8220;default=nk=1:nw=1&#8221;,\n        str(src),\n    ])\n    if dur:\n        return dur\n    # 2) stream.duration\uff08\u52d5\u753b\u30b9\u30c8\u30ea\u30fc\u30e0\uff09\n    dur = _run_ffprobe_val(ffprobe, [\n        &#8220;-v&#8221;, &#8220;error&#8221;,\n        &#8220;-select_streams&#8221;, &#8220;v:0&#8221;,\n        &#8220;-show_entries&#8221;, &#8220;stream=duration&#8221;,\n        &#8220;-of&#8221;, &#8220;default=nk=1:nw=1&#8221;,\n        str(src),\n    ])\n    if dur:\n        return dur\n    # 3) nb_frames \/ avg_frame_rate \u304b\u3089\u63a8\u5b9a\n    try:\n        nb = subprocess.run([ffprobe, &#8220;-v&#8221;, &#8220;error&#8221;, &#8220;-select_streams&#8221;, &#8220;v:0&#8221;,\n                             &#8220;-show_entries&#8221;, &#8220;stream=nb_frames&#8221;,\n                             &#8220;-of&#8221;, &#8220;default=nk=1:nw=1&#8221;, str(src)],\n                            capture_output=True, text=True, check=True).stdout.strip()\n        fps_s = subprocess.run([ffprobe, &#8220;-v&#8221;, &#8220;error&#8221;, &#8220;-select_streams&#8221;, &#8220;v:0&#8221;,\n                                &#8220;-show_entries&#8221;, &#8220;stream=avg_frame_rate&#8221;,\n                                &#8220;-of&#8221;, &#8220;default=nk=1:nw=1&#8221;, str(src)],\n                               capture_output=True, text=True, check=True).stdout.strip()\n        if nb and fps_s and &#8220;\/&#8221; in fps_s:\n            num, den = fps_s.split(&#8220;\/&#8221;, 1)\n            num = float(num); den = float(den) if float(den) != 0 else 1.0\n            fps = num \/ den if den != 0 else float(num)\n            frames = float(nb)\n            if fps > 0 and frames > 0:\n                return frames \/ fps\n    except Exception:\n        pass\n    return None\n\ndef write_progress_csv(csv_path: Path, samples: List[Tuple[float, float]]) -> None:\n    lines = [&#8220;time_sec,percent&#8221;]\n    lines += [f&#8221;{t:.3f},{p:.3f}&#8221; for t, p in samples]\n    csv_path.write_text(&#8220;\\n&#8221;.join(lines), encoding=&#8221;utf-8&#8243;)\n\ndef write_progress_svg(svg_path: Path, samples: List[Tuple[float, float]]) -> None:\n    if not samples:\n        svg_path.write_text(&#8220;<svg xmlns='http:\/\/www.w3.org\/2000\/svg' width='800' height='240'><\/svg>&#8220;, encoding=&#8221;utf-8&#8243;)\n        return\n    W, H, P = 800, 240, 32\n    xs = [t for t, _ in samples]\n    ys = [p for _, p in samples]\n    tmax = max(xs) if max(xs) > 0 else 1.0\n    def sx(t): return P + (W &#8211; 2*P) * (t \/ tmax)\n    def sy(p): return H &#8211; P &#8211; (H &#8211; 2*P) * (p \/ 100.0)\n    pts = &#8221; &#8220;.join([f&#8221;{sx(t):.1f},{sy(p):.1f}&#8221; for t, p in samples])\n    grid = []\n    for k in [0,25,50,75,100]:\n        y = sy(k)\n        grid.append(f&#8221;<line x1='{P}' y1='{y:.1f}' x2='{W-P}' y2='{y:.1f}' stroke='#ddd'\/>&#8220;)\n        grid.append(f&#8221;<text x='5' y='{y+4:.1f}' font-size='10' fill='#555'>{k}%<\/text>&#8220;)\n    frame = f&#8221;<rect x='{P}' y='{P}' width='{W-2*P}' height='{H-2*P}' fill='none' stroke='#888'\/>&#8221;\n    lastp = ys[-1]\n    label = f&#8221;<text x='{W-60}' y='{P+14}' font-size='12' fill='#222'>final: {lastp:.1f}%<\/text>&#8221;\n    svg = f&#8221;&#8221;&#8221;<svg xmlns='http:\/\/www.w3.org\/2000\/svg' width='{W}' height='{H}'>\n  <rect width='100%' height='100%' fill='white'\/>\n  {&#8221;.join(grid)}\n  {frame}\n  <polyline fill='none' stroke='#0b79d0' stroke-width='2' points='{pts}'\/>\n  {label}\n<\/svg>&#8220;&#8221;&#8221;\n    svg_path.write_text(svg, encoding=&#8221;utf-8&#8243;)\n\ndef run_ffmpeg_with_progress(ffmpeg: str, src: Path, dst_mp4: Path, vopts: List[str],\n                             enable_progress: bool = True) -> None:\n    csv_path = dst_mp4.with_name(dst_mp4.stem + &#8220;_progress.csv&#8221;)\n    svg_path = dst_mp4.with_name(dst_mp4.stem + &#8220;_progress.svg&#8221;)\n\n    duration = ffprobe_duration_sec(ffmpeg, src) or 0.0\n\n    base = [ffmpeg, &#8220;-y&#8221;, &#8220;-hide_banner&#8221;, &#8220;-loglevel&#8221;, &#8220;error&#8221;]\n    filters = build_filters()\n    common_tail = [\n        &#8220;-c:a&#8221;, &#8220;aac&#8221;, &#8220;-b:a&#8221;, &#8220;160k&#8221;,\n        &#8220;-movflags&#8221;, &#8220;+faststart&#8221;,\n        &#8220;-map_metadata&#8221;, &#8220;0&#8221;,\n        &#8220;-progress&#8221;, &#8220;pipe:1&#8221;,\n        str(dst_mp4),\n    ]\n    cmd = base + [&#8220;-i&#8221;, str(src)] + filters + vopts + common_tail\n\n    samples: List[Tuple[float, float]] = []\n    start = time.monotonic()\n    out_time_ms = 0.0\n\n    with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1) as proc:\n        if enable_progress and proc.stdout is not None:\n            for raw in proc.stdout:\n                line = raw.strip()\n                if line.startswith(&#8220;out_time_ms=&#8221;):\n                    try:\n                        out_time_ms = float(line.split(&#8220;=&#8221;, 1)[1])\n                        tsec = out_time_ms \/ 1_000_000.0\n                        if duration > 0:\n                            pct = max(0.0, min(100.0, (tsec \/ duration) * 100.0))\n                        else:\n                            # duration\u4e0d\u660e\u306a\u3089\u300c\u7d4c\u904e\u6642\u9593\u3067\u53f3\u80a9\u4e0a\u304c\u308a\u300d\u3060\u304c 100% \u306f end \u3067\u4ed8\u4e0e\n                            elapsed = time.monotonic() &#8211; start\n                            pct = min(99.0, elapsed % 99.0)  # \u64ec\u4f3c\uff08\u898b\u305f\u76ee\u7528\uff09\n                        elapsed = time.monotonic() &#8211; start\n                        samples.append((elapsed, pct))\n                        print(f&#8221;    progress: {pct:5.1f}%  (t={tsec:7.2f}s \/ dur={duration:7.2f}s)&#8221;, end=&#8221;\\r&#8221;)\n                    except Exception:\n                        pass\n                elif line == &#8220;progress=end&#8221;:\n                    elapsed = time.monotonic() &#8211; start\n                    samples.append((elapsed, 100.0))\n        ret = proc.wait()\n\n    print()  # \u884c\u672b\u6574\u5f62\n\n    if ret != 0:\n        try:\n            if csv_path.exists(): csv_path.unlink()\n            if svg_path.exists(): svg_path.unlink()\n        except Exception:\n            pass\n        raise subprocess.CalledProcessError(ret, cmd)\n\n    try:\n        write_progress_csv(csv_path, samples)\n        write_progress_svg(svg_path, samples)\n        print(f&#8221;  progress: {csv_path.name}, {svg_path.name}&#8221;)\n    except Exception as e:\n        print(f&#8221;  WARN: \u9032\u6357\u30d5\u30a1\u30a4\u30eb\u306e\u4f5c\u6210\u306b\u5931\u6557: {e}&#8221;)\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- \u30e1\u30bf\u30c7\u30fc\u30bf\u4e38\u30b3\u30d4\u30fc &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef copy_metadata_to_output(exiftool: str, src: Path, dst: Path) -> bool:\n    cmd = [\n        exiftool, &#8220;-q&#8221;, &#8220;-m&#8221;, &#8220;-P&#8221;, &#8220;-overwrite_original&#8221;,\n        &#8220;-TagsFromFile&#8221;, str(src),\n        &#8220;-all:all&#8221;, &#8220;-time:all&#8221;, &#8220;-XMP:all&#8221;, &#8220;-Keys:all&#8221;, &#8220;-UserData:all&#8221;,\n        str(dst),\n    ]\n    res = subprocess.run(cmd, capture_output=True)\n    return res.returncode == 0\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- GPX \u5438\u51fa\u3057\u2192\u6574\u5f62\u21921Hz\u9593\u5f15\u304d &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef run_exiftool_template_raw(exiftool: str, src: Path, fmt: Path) -> Optional[str]:\n    &#8220;&#8221;&#8221;\u30c6\u30f3\u30d7\u30ec\u3067\u201c\u751fGPX\u201d\u3092\u6a19\u6e96\u51fa\u529b\u306b\u5410\u304b\u305b\u3066\u6587\u5b57\u5217\u3067\u8fd4\u3059\uff08\u3042\u306a\u305f\u306e\u5b9f\u7e3e\u3042\u308b\u65b9\u5f0f\uff09\u3002&#8221;&#8221;&#8221;\n    cmd = [exiftool, &#8220;-q&#8221;, &#8220;-ee&#8221;, &#8220;-p&#8221;, str(fmt), str(src)]\n    res = subprocess.run(cmd, check=False, capture_output=True)\n    if res.returncode != 0:\n        return None\n    text = res.stdout.decode(&#8220;utf-8&#8243;, errors=&#8221;replace&#8221;)\n    return text if &#8220;<trkpt \" in text else None\n\ndef parse_trkpts_from_raw_gpx(xml: str) -> List[Dict[str, str]]:\n    &#8220;&#8221;&#8221;\u30c6\u30f3\u30d7\u30ecGPX(<trkpt>)\u304b\u3089 lat\/lon\/time\/ele\/speed \u3092\u7d20\u6734\u62bd\u51fa\u3002&#8221;&#8221;&#8221;\n    pts: List[Dict[str,str]] = []\n    for block in xml.split(&#8220;<trkpt \")[1:]:\n        try:\n            frag = block.split(\"<\/trkpt>&#8220;, 1)[0]\n            lat = frag.split(&#8216;lat=&#8221;&#8216;,1)[1].split(&#8216;&#8221;&#8216;,1)[0]\n            lon = frag.split(&#8216;lon=&#8221;&#8216;,1)[1].split(&#8216;&#8221;&#8216;,1)[0]\n            t   = frag.split(&#8220;<time>&#8220;,1)[1].split(&#8220;<\/time>&#8220;,1)[0]\n            ele = frag.split(&#8220;<ele>&#8220;,1)[1].split(&#8220;<\/ele>&#8220;,1)[0]\n            spd = frag.split(&#8220;<speed>&#8220;,1)[1].split(&#8220;<\/speed>&#8220;,1)[0]\n            pts.append({&#8220;lat&#8221;:lat,&#8221;lon&#8221;:lon,&#8221;time&#8221;:t,&#8221;ele&#8221;:ele,&#8221;speed&#8221;:spd})\n        except Exception:\n            continue\n    return pts\n\ndef _parse_dt_any(tstr: str) -> Optional[datetime]:\n    t = tstr.strip().replace(&#8221; &#8220;, &#8220;T&#8221;).replace(&#8220;\/&#8221;, &#8220;-&#8220;)\n    # \u4ee3\u8868\u7684\u306a\u8868\u8a18\u3092\u5e45\u5e83\u304f\u8a31\u5bb9\n    for fmt in (&#8220;%Y-%m-%dT%H:%M:%S.%fZ&#8221;, &#8220;%Y-%m-%dT%H:%M:%S.%f&#8221;,\n                &#8220;%Y-%m-%dT%H:%M:%SZ&#8221;, &#8220;%Y-%m-%dT%H:%M:%S&#8221;,\n                &#8220;%Y:%m:%dT%H:%M:%S.%f&#8221;, &#8220;%Y:%m:%dT%H:%M:%S&#8221;):\n        try:\n            return datetime.strptime(t, fmt)\n        except Exception:\n            continue\n    return None\n\n_num_pat = re.compile(r&#8221;[-+]?\\d+(?:\\.\\d+)?&#8221;)\n\ndef _to_numeric_str(val: str, default: str=&#8221;0&#8243;) -> str:\n    &#8220;&#8221;&#8221;&#8216;123.4 m\/s&#8217; \u306e\u3088\u3046\u306a\u6587\u5b57\u5217\u304b\u3089\u6570\u5024\u90e8\u5206\u3060\u3051\u3092\u629c\u304d\u51fa\u3057\u3066\u8fd4\u3059\u3002&#8221;&#8221;&#8221;\n    if val is None:\n        return default\n    m = _num_pat.search(str(val))\n    return m.group(0) if m else default\n\ndef decimate_to_1hz(points: List[Dict[str,str]]) -> List[Dict[str,str]]:\n    &#8220;&#8221;&#8221;1\u79d2\u3054\u3068\u306b\u6700\u521d\u306e\u70b9\u3092\u63a1\u7528\uff08floor\u79d2\uff09\u3002ele\/speed\u306f\u6570\u5024\u62bd\u51fa\u3057\u3066\u51fa\u529b\u3002&#8221;&#8221;&#8221;\n    per_sec: Dict[int, Dict[str,str]] = {}\n    for r in points:\n        if not r.get(&#8220;lat&#8221;) or not r.get(&#8220;lon&#8221;) or not r.get(&#8220;time&#8221;):\n            continue\n        dt = _parse_dt_any(r[&#8220;time&#8221;])\n        if not dt:\n            continue\n        dt_floor = dt.replace(microsecond=0)\n        sec_key = int(dt_floor.timestamp())\n        if sec_key in per_sec:\n            continue\n        per_sec[sec_key] = {\n            &#8220;lat&#8221;: r[&#8220;lat&#8221;],\n            &#8220;lon&#8221;: r[&#8220;lon&#8221;],\n            &#8220;ele&#8221;: _to_numeric_str(r.get(&#8220;ele&#8221;,&#8221;0&#8243;)),\n            &#8220;speed&#8221;: _to_numeric_str(r.get(&#8220;speed&#8221;,&#8221;0&#8243;)),\n            &#8220;time&#8221;: dt_floor.strftime(&#8220;%Y-%m-%dT%H:%M:%S.%f&#8221;),  # \u4f8b\u306b\u5408\u308f\u305b\u30666\u6841\u5c0f\u6570\n        }\n    return [per_sec[k] for k in sorted(per_sec.keys())]\n\ndef write_gpx_like_example(dst_gpx: Path, points_1hz: List[Dict[str,str]]) -> bool:\n    &#8220;&#8221;&#8221;example.gpx\u4e92\u63db\uff1agpxtpx\u540d\u524d\u7a7a\u9593\uff0b\u4e8c\u91cd<extensions>\uff0bcreator\u6587\u5b57\u5217\u306a\u3069\u3092\u518d\u69cb\u6210\u3002&#8221;&#8221;&#8221;\n    if not points_1hz:\n        return False\n    head = &#8220;&#8221;&#8221;<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"1.1\"\n xmlns=\"http:\/\/www.topografix.com\/GPX\/1\/1\"\n xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n xmlns:gpxtpx=\"http:\/\/www.garmin.com\/xmlschemas\/TrackPointExtension\/v1\"\n xsi:schemaLocation=\"http:\/\/www.topografix.com\/GPX\/1\/1\n http:\/\/www.topografix.com\/GPX\/1\/1\/gpx.xsd\n http:\/\/www.garmin.com\/xmlschemas\/TrackPointExtension\/v1\n http:\/\/www.garmin.com\/xmlschemas\/TrackPointExtensionv1.xsd\"\n creator=\"gpx.py -- https:\/\/github.com\/tkrajina\/gpxpy\">\n  <trk>\n    <trkseg>\n&#8220;&#8221;&#8221;\n    tail = &#8220;&#8221;&#8221;    <\/trkseg>\n  <\/trk>\n<\/gpx>\n&#8220;&#8221;&#8221;\n    lines = [head]\n    for p in points_1hz:\n        lines.append(\nf&#8221;&#8221;&#8221;      <trkpt lat=\"{p['lat']}\" lon=\"{p['lon']}\">\n        <ele>{p[&#8216;ele&#8217;]}<\/ele>\n        <time>{p[&#8216;time&#8217;]}<\/time>\n        <extensions>\n          <extensions>\n            <gpxtpx:TrackPointExtension>\n              <gpxtpx:hr>0<\/gpxtpx:hr>\n              <gpxtpx:cad>0<\/gpxtpx:cad>\n              <gpxtpx:speed>{p[&#8216;speed&#8217;]}<\/gpxtpx:speed>\n              <gpxtpx:distance>0<\/gpxtpx:distance>\n            <\/gpxtpx:TrackPointExtension>\n          <\/extensions>\n        <\/extensions>\n      <\/trkpt>\n&#8220;&#8221;&#8221;\n        )\n    lines.append(tail)\n    dst_gpx.write_text(&#8220;&#8221;.join(lines), encoding=&#8221;utf-8&#8243;)\n    return True\n\n# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- \u30e1\u30a4\u30f3\u51e6\u7406\uff08GPX\u2192\u30a8\u30f3\u30b3\u30fc\u30c9\uff09 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-\n\ndef process_one(src: Path, ffmpeg: str, exiftool: str, fmt: Path,\n                overwrite: bool, hwenc: str, progress: bool) -> None:\n    if not is_video(src):\n        print(f&#8221;SKIP (\u62e1\u5f35\u5b50\u975e\u5bfe\u5fdc): {src}&#8221;)\n        return\n\n    stem = src.stem\n    out_mp4 = src.with_name(f&#8221;{stem}_1280_720.mp4\u300d\n    out_gpx = src.with_name(f&#8221;{stem}_1280_720.gpx&#8221;)\n\n    # &#8212;- (1) \u5438\u51fa\u3057 \u2192 (2) \u6574\u5f62\uff0b1Hz \u9593\u5f15\u304d\uff08\u5148\u306bGPX\u3092\u78ba\u5b9a\uff09\n    if out_gpx.exists() and not overwrite:\n        print(f&#8221;EXIST: {out_gpx.name} -> \u4e0a\u66f8\u304d\u3057\u307e\u305b\u3093 (&#8211;overwrite)&#8221;)\n    else:\n        print(f&#8221;[GPX]    {src.name} -> {out_gpx.name} (extract\u2192format\u21921Hz)&#8221;)\n        raw_xml = run_exiftool_template_raw(exiftool, src, fmt)\n        if not raw_xml:\n            try:\n                if out_gpx.exists(): out_gpx.unlink()\n            except Exception: pass\n            print(&#8221;  WARN: GPS\u30c8\u30e9\u30c3\u30af\u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u62bd\u51fa\u30bc\u30ed (GPX\u672a\u4f5c\u6210)&#8221;)\n        else:\n            pts = parse_trkpts_from_raw_gpx(raw_xml)\n            pts_1hz = decimate_to_1hz(pts)\n            if write_gpx_like_example(out_gpx, pts_1hz):\n                print(f&#8221;  OK: {out_gpx.name}  (points: {len(pts)} \u2192 1Hz: {len(pts_1hz)})&#8221;)\n            else:\n                try:\n                    if out_gpx.exists(): out_gpx.unlink()\n                except Exception: pass\n                print(&#8221;  WARN: \u6574\u5f62\/\u9593\u5f15\u304d\u3067\u6709\u52b9\u70b9\u306a\u3057 (GPX\u672a\u4f5c\u6210)&#8221;)\n\n    # &#8212;- (3) \u30a8\u30f3\u30b3\u30fc\u30c9\uff086Mbps\u56fa\u5b9a\u3001libx264\u4e0d\u4f7f\u7528\uff09\n    if out_mp4.exists() and not overwrite:\n        print(f&#8221;EXIST: {out_mp4.name} -> \u4e0a\u66f8\u304d\u3057\u307e\u305b\u3093 (&#8211;overwrite)&#8221;)\n    else:\n        print(f&#8221;[Encode] {src.name} -> {out_mp4.name}&#8221;)\n        candidates = pick_encoder_list(ffmpeg, hwenc)\n        last_err = None\n        for name, vopts in candidates:\n            print(f&#8221;  -> \u8a66\u884c: {name}&#8221;)\n            try:\n                run_ffmpeg_with_progress(ffmpeg, src, out_mp4, vopts, enable_progress=progress)\n                print(f&#8221;  OK: {name} \u3092\u4f7f\u7528 (6Mbps)&#8221;)\n                # &#8212;- (5) \u30e1\u30bf\u30c7\u30fc\u30bf\u4e38\u30b3\u30d4\u30fc\n                if not copy_metadata_to_output(exiftool, src, out_mp4):\n                    print(&#8221;  WARN: \u30e1\u30bf\u30c7\u30fc\u30bf\u306e\u30b3\u30d4\u30fc\u306b\u4e00\u90e8\u5931\u6557\uff08\u5fc5\u8981\u30bf\u30b0\u304c\u8db3\u308a\u306a\u3044\u53ef\u80fd\u6027\uff09&#8221;)\n                else:\n                    print(&#8221;  META: \u5143\u52d5\u753b\u306e\u30bf\u30b0\u3092\u30b3\u30d4\u30fc\u6e08\u307f&#8221;)\n                break\n            except subprocess.CalledProcessError as e:\n                last_err = e\n                print(f&#8221;     \u5931\u6557: {name}\uff08\u6b21\u5019\u88dc\u3078\uff09&#8221;)\n                try:\n                    if out_mp4.exists():\n                        out_mp4.unlink()\n                except Exception:\n                    pass\n        else:\n            if last_err:\n                raise last_err\n            raise RuntimeError(&#8220;\u30a8\u30f3\u30b3\u30fc\u30c9\u5168\u6ec5&#8221;)\n\ndef collect_targets(path: Path):\n    if path.is_dir():\n        return [p for p in path.rglob(&#8220;*&#8221;) if p.is_file() and is_video(p)]\n    elif path.is_file():\n        return [path]\n    else:\n        sys.exit(f&#8221;ERROR: \u30d1\u30b9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093: {path}&#8221;)\n\ndef main():\n    ap = argparse.ArgumentParser(description=&#8221;GoPro: GPX\u5148\u884c(\u6574\u5f62+1Hz) \u2192 H.264 1280&#215;720\/6Mbps\uff08libx264\u4e0d\u4f7f\u7528\uff09&#8221;)\n    ap.add_argument(&#8220;path&#8221;, help=&#8221;\u52d5\u753b\u30d5\u30a1\u30a4\u30eb or \u30d5\u30a9\u30eb\u30c0&#8221;)\n    ap.add_argument(&#8220;&#8211;ffmpeg&#8221;, dest=&#8221;ffmpeg_path&#8221;, default=None, help=&#8221;ffmpeg.exe \u306e\u30d1\u30b9\uff08\u672a\u6307\u5b9a: \u540c\u68b1\u2192PATH\uff09&#8221;)\n    ap.add_argument(&#8220;&#8211;exiftool&#8221;, dest=&#8221;exiftool_path&#8221;, default=None, help=&#8221;exiftool.exe \u306e\u30d1\u30b9\uff08\u672a\u6307\u5b9a: \u540c\u68b1\u2192PATH\uff09&#8221;)\n    ap.add_argument(&#8220;&#8211;overwrite&#8221;, action=&#8221;store_true&#8221;, help=&#8221;\u65e2\u5b58\u51fa\u529b\u3092\u4e0a\u66f8\u304d&#8221;)\n    ap.add_argument(&#8220;&#8211;hwenc&#8221;, default=&#8221;auto&#8221;, choices=[&#8220;auto&#8221;,&#8221;nvenc&#8221;,&#8221;qsv&#8221;,&#8221;amf&#8221;,&#8221;mf&#8221;],\n                    help=&#8221;\u30a8\u30f3\u30b3\u30fc\u30c0\u9078\u629e: auto(\u65e2\u5b9a) \/ qsv \/ nvenc \/ amf \/ mf\uff08libx264\u306b\u306f\u843d\u3061\u307e\u305b\u3093\uff09&#8221;)\n    ap.add_argument(&#8220;&#8211;no-progress&#8221;, action=&#8221;store_true&#8221;, help=&#8221;\u9032\u6357CSV\/SVG\u3092\u51fa\u529b\u3057\u306a\u3044&#8221;)\n    args = ap.parse_args()\n\n    ffmpeg = resolve_tool(&#8220;ffmpeg&#8221;, args.ffmpeg_path, Path(&#8220;tools\/ffmpeg\/ffmpeg.exe&#8221;))\n    exiftool = resolve_tool(&#8220;exiftool&#8221;, args.exiftool_path, Path(&#8220;tools\/exiftool\/exiftool.exe&#8221;))\n\n    fmt = build_gpx_template()\n    try:\n        targets = collect_targets(Path(args.path))\n        if not targets:\n            print(&#8220;\u5bfe\u8c61\u52d5\u753b\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\uff08.mp4 .mov .m4v\uff09\u3002&#8221;)\n            return\n        for i, src in enumerate(targets, 1):\n            print(f&#8221;\\n[{i}\/{len(targets)}] {src}&#8221;)\n            try:\n                process_one(\n                    src, ffmpeg, exiftool, fmt,\n                    overwrite=args.overwrite,\n                    hwenc=args.hwenc,\n                    progress=(not args.no_progress),\n                )\n            except subprocess.CalledProcessError as e:\n                print(f&#8221;ERROR: {src.name} \u306e\u51e6\u7406\u306b\u5931\u6557: {e}&#8221;)\n    finally:\n        try:\n            fmt.unlink()\n        except Exception:\n            pass\n\nif __name__ == &#8220;__main__&#8221;:\n    main()\n    <\/textarea>\n  <\/details>\n<\/section>\n\n\n<section>\n  <h2>\u6700\u5f8c\u306b\u3072\u3068\u3053\u3068<\/h2>\n  <p>\n    \u300cGPS\u4ed8\u304dGoPro\u7d20\u6750\u3092\u3001<strong>\u5730\u56f3\u9023\u643a\u3057\u3084\u3059\u3044GPX<\/strong>\u3068<strong>\u914d\u4fe1\u7528\u306e\u8efd\u3044\u52d5\u753b<\/strong>\u306b\u4e00\u767a\u3067\u5206\u89e3\u3057\u305f\u3044\u300d\u2015\u2015\u305d\u306e\u30cb\u30fc\u30ba\u306b\u76f4\u7403\u3067\u5fdc\u3048\u308b\u30c4\u30fc\u30eb\u3067\u3059\u3002\n    \u6b20\u3051\u3066\u3044\u308b\u306e\u306fNVENC\u30b5\u30dd\u30fc\u30c8\u304f\u3089\u3044\u3002\u5fc5\u8981\u306a\u3089\u4e00\u884c\u8ffd\u52a0\u3067OK\u3002\u9060\u56de\u308a\u305b\u305a\u3001\u5b9f\u52d9\u3067\u201c\u3059\u3050\u4f7f\u3048\u308b\u201d\u8a2d\u8a08\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\n  <\/p>\n  <div class=\"ok\">\u73fe\u5834\u3067\u56de\u3059\u524d\u306b\uff1a\u30b5\u30f3\u30d7\u30eb1\u672c\u3067<code>--overwrite<\/code>\u306a\u3057\uff06<code>--hwenc auto<\/code>\u304b\u3089\u30c6\u30b9\u30c8\u63a8\u5968\u3002<br>\u00a9\u682a\u5f0f\u4f1a\u793e\u30d3\u30fc\u30fb\u30ca\u30ec\u30c3\u30b8\u30fb\u30c7\u30b6\u30a4\u30f3<\/div>\n<\/section>\n\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>GoPro\u52d5\u753b\u2192GPX\u62bd\u51fa\u30fb1Hz\u6574\u5f62\u30fb720p\u518d\u30a8\u30f3\u30b3\u30fc\u30c9\u30fb\u9032\u6357\u53ef\u8996\u5316\u30fb\u30e1\u30bf\u30c7\u30fc\u30bf\u7d99\u627f\u30c4\u30fc\u30eb\uff08\u30bd\u30fc\u30b9\u4ed8\u304d\uff09 \u3053\u306e\u30b9\u30af\u30ea\u30d7\u30c8\u306f\u4f55\u3092\u3059\u308b\uff1f\uff08\u30bd\u30fc\u30b9\u4ed8\u304d\u89e3\u8aac\uff09 GoPro\u306e\u52d5\u753b\u304b\u3089GPS\u8ecc\u8de1\uff08GPX\uff09\u3092\u629c\u304d\u51fa\u3057\u30011\u79d2\u9593\u9694\u306b\u6574 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"saved_in_kubio":false,"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"vkexunit_cta_each_option":"","footnotes":""},"categories":[6],"tags":[76,77],"class_list":["post-1669","post","type-post","status-publish","format-standard","hentry","category-programing","tag-76","tag-77"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/posts\/1669","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1669"}],"version-history":[{"count":2,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/posts\/1669\/revisions"}],"predecessor-version":[{"id":1671,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=\/wp\/v2\/posts\/1669\/revisions\/1671"}],"wp:attachment":[{"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1669"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1669"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/beeknowledge.co.jp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1669"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}