So I have started seeing lots of people starting to publish videos where they ask generative AI to generate the code for an entire app and fairly complex apps are getting generated.
Thought I will try it out myself as well.
The cover image is generated using AlphaCTR.com
The Prompt
So the idea is simple. I want to make a GUI wrapper for yt-dlp - a tool I frequently use to download videos (or parts thereof) from YouTube.
I asked ChatGPT (GPT4) to build this app for me.
So here was my prompt. (It is fairly detailed).
I want to make a Flutter app that downloads videos using the 'yt-dlp' tool.
Assume the following
1. I do not need to setup yt-dlp, it exists on my PC already.
2. Do not help me with Flutter installation and plugin adding steps.
3. Only show the code for the lib/main.dart file
The app's UI will have the following
1. Title bar: "YouTube Downloader GUI"
2. Input Box [id: ytUrl, placeholder: "youtube video url"]
3. A row of 3 checkboxes
a. "Video" [id: dlVid, default: checked]
b. "Audio" [id: dlAud, default: unchecked]
c. "Thumbnail" [id: dlThumb, default: unchecked]
4. Two input boxes for start and end time
a. "Start time" [id: timeStart]
b. "End Time" [id: timeEnd]
5. Two dropdown boxes to select quality of audio and video
a. id: qualVid, choices: [480p, 720p, 1080p, 2K, 4K], default: 1080p
b. id: qualAud, choices: [64k, 128k, 192k, 256k, 320k] default: 192k
The logic for downloading should be this.
1. If dlAud = true, download audio separately
2. If dlThumb = true, download thumbnail too
3. If start and end time are given, download only that portion of the video
4. If ytUrl is not provided or doesn't contain 'youtube.com' in it show a Dialog "Enter valid YouTube URL"
5. Factor in the qualVid and qualAud when downloading audio and video.
6. Download videos in mp4 form and audio in mp3 form
Highlighting a few things here
I explicitly asked only to generate the
lib/main.dart
code for me because otherwise ChatGPT by default provides all the info required to setup a Flutter project and install dependencies. Since I am well versed with Flutter at a basic level to do these things myself, I asked it to avoid it for faster outputI am building a Flutter app (and not say, React Native Desktop) especially because this is a platform I am slightly familiar with and I can debug the final output
The Initial Output
So here is the code that ChatGPT generated for me
import 'package:flutter/material.dart';
import 'package:process_run/cmd_run.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YouTube Downloader GUI',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String ytUrl;
bool dlVid = true;
bool dlAud = false;
bool dlThumb = false;
TimeOfDay timeStart;
TimeOfDay timeEnd;
String qualVid = '1080p';
String qualAud = '192k';
List<String> qualVidOptions = ['480p', '720p', '1080p', '2K', '4K'];
List<String> qualAudOptions = ['64k', '128k', '192k', '256k', '320k'];
void download() async {
if (ytUrl == null || !ytUrl.contains('youtube.com')) {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Text('Enter valid YouTube URL'),
),
);
return;
}
String command = 'yt-dlp -f \'bestvideo[height<=${qualVid.replaceAll('p', '')}]'
'+bestaudio/best[height<=${qualVid.replaceAll('p', '')}]\' $ytUrl';
if (dlAud) command += ' -x --audio-format mp3 --audio-quality ${qualAud}';
if (dlThumb) command += ' --write-thumbnail';
if (timeStart != null && timeEnd != null)
command +=
' --postprocessor-args "-ss ${timeStart.format(context)} -to ${timeEnd.format(context)}"';
await runCmd(ProcessCmd(command.split(' ')[0], command.split(' ').sublist(1)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('YouTube Downloader GUI'),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
TextField(
onChanged: (value) => ytUrl = value,
decoration: InputDecoration(
labelText: 'YouTube Video URL',
),
),
Row(
children: <Widget>[
Checkbox(
value: dlVid,
onChanged: (bool value) {
setState(() {
dlVid = value;
});
},
),
Text('Video'),
Checkbox(
value: dlAud,
onChanged: (bool value) {
setState(() {
dlAud = value;
});
},
),
Text('Audio'),
Checkbox(
value: dlThumb,
onChanged: (bool value) {
setState(() {
dlThumb = value;
});
},
),
Text('Thumbnail'),
],
),
Row(
children: [
Expanded(
child: TextField(
onTap: () async {
TimeOfDay time = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (time != null) setState(() => timeStart = time);
},
readOnly: true,
decoration: InputDecoration(
labelText: 'Start Time',
hintText: timeStart?.format(context) ?? '',
),
),
),
SizedBox(width: 16),
Expanded(
child: TextField(
onTap: () async {
TimeOfDay time = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (time != null) setState(() => timeEnd = time);
},
readOnly: true,
decoration: InputDecoration(
labelText: 'End Time',
hintText: timeEnd?.format(context) ?? '',
),
),
),
],
),
DropdownButton(
value: qualVid,
items: qualVidOptions
.map((value) => DropdownMenuItem(
child: Text(value),
value: value,
))
.toList(),
onChanged: (String value) {
setState(() {
qualVid = value;
});
},
),
DropdownButton(
value: qualAud,
items: qualAudOptions
.map((value) => DropdownMenuItem(
child: Text(value),
value: value,
))
.toList(),
onChanged: (String value) {
setState(() {
qualAud = value;
});
},
),
ElevatedButton(
onPressed: download,
child: Text('Download'),
),
],
),
),
);
}
}
It does also mention that this might not cover all corner cases and be mindful of YouTube policies
Trying to use it
Let's see what happens when I try to use it. I am not sure if this code will work straight out of the box or not!
So it didn't work out of the box, and the main reason for that is that ChatGPT's knowledge cutoff date is Sept 2021, which means most things in Flutter and Dart that have evolved since then wouldn't have found its way into ChatGPT's codex. One particular thing that affects is that ChatGPT-generated Flutter code doesn't use const
constructors. Because it would not have been trained on much code with const
Here is a full diff of the changes I had to do to get it just working.
https://github.com/championswimmer/yt_dlp_ui/commit/8a1fe9ba3a2bb33120779138b66222c804a25859
Some highlights
ofcourse, lots of
const
additions
not understanding 2023-era Dart null safety
using some older APIs of the
process_run
library
Getting it to work
Had to make one final change (which ChatGPT already had warned me about) - to disable MacOS sandbox mode, to be able to run shelle commands
Basically go to macos/Runner/DebugProfile.entitlements
and
<key>com.apple.security.app-sandbox</key>
<false/>
Mostly after these changes, it basically works!
The start/end time input boxes are timepickers, which we need to fix!
I stopped the download midway that's why it didn't finish
Will need to fix how the video/audio quality is translated in the shell command
Conclusion
I think this is pretty good. Obviously the way this will get weaponised won't be us talking to a damn chatbot and asking it to code. There will be better ways this will integrate into the coding workflow.
I will next try to achieve the same using smol-dev-js which is based on smol.ai and I'll probably write up about that when I do.
Till then, this is fairly promising. And I will finally turn the Small App Ideas.md
page from by Obsidian into actual apps maybe!